Download as pdf or txt
Download as pdf or txt
You are on page 1of 70

Data Science Using JDBC And MySQL

With Object Oriented Approach and


Apache Netbeans IDE 1st Edition Vivian
Siahaan
Visit to download the full and correct content document:
https://ebookmeta.com/product/data-science-using-jdbc-and-mysql-with-object-orient
ed-approach-and-apache-netbeans-ide-1st-edition-vivian-siahaan/
More products digital (pdf, epub, mobi) instant
download maybe you interests ...

Object Oriented Data Analysis 1st Edition Marron

https://ebookmeta.com/product/object-oriented-data-analysis-1st-
edition-marron/

Object Oriented Modeling and Design Using UML 2nd


Edition Singh

https://ebookmeta.com/product/object-oriented-modeling-and-
design-using-uml-2nd-edition-singh/

Concise Guide to Object Oriented Programming An


Accessible Approach Using Java Undergraduate Topics in
Computer Science 1st Edition Kingsley Sage

https://ebookmeta.com/product/concise-guide-to-object-oriented-
programming-an-accessible-approach-using-java-undergraduate-
topics-in-computer-science-1st-edition-kingsley-sage/

Object Oriented Data Analysis 1st Edition James Stephen


Marron

https://ebookmeta.com/product/object-oriented-data-analysis-1st-
edition-james-stephen-marron/
Python 3 Object oriented Programming Building robust
and maintainable software with object oriented design
patterns in Python 2nd Edition Phillips

https://ebookmeta.com/product/python-3-object-oriented-
programming-building-robust-and-maintainable-software-with-
object-oriented-design-patterns-in-python-2nd-edition-phillips/

Common Data Sense for Professionals: A Process-Oriented


Approach for Data-Science Projects 1st Edition Rajesh
Jugulum

https://ebookmeta.com/product/common-data-sense-for-
professionals-a-process-oriented-approach-for-data-science-
projects-1st-edition-rajesh-jugulum/

Object-Oriented Python Irv Kalb

https://ebookmeta.com/product/object-oriented-python-irv-kalb/

Object Oriented Programming with Swift 2 1st Edition


Gastón C Hillar

https://ebookmeta.com/product/object-oriented-programming-with-
swift-2-1st-edition-gaston-c-hillar/

Pro Apache NetBeans: Building Applications on the Rich


Client Platform 1st Edition Ioannis Kostaras

https://ebookmeta.com/product/pro-apache-netbeans-building-
applications-on-the-rich-client-platform-1st-edition-ioannis-
kostaras/
DATA SCIENCE
USING JDBC AND MYSQL
WITH OBJECT-ORIENTED APPROACH
AND APACHE NETBEANS IDE
DATA SCIENCE
USING JDBC AND MYSQL
WITH OBJECT-ORIENTED APPROACH
AND APACHE NETBEANS IDE

First Edition

VIVIAN SIAHAAN
RISMON HASIHOLAN SIANIPAR

Copyright © 2023 BALIGE Publishing


All rights reserved. No part of this book may be reproduced, stored in a retrieval system,
or transmitted in any form or by any means, without the prior written permission of the
publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the
information presented. However, the information contained in this book is sold without
warranty, either express or implied. Neither the authors, nor BALIGE Publishing or its
dealers and distributors, will be held liable for any damages caused or alleged to have
been caused directly or indirectly by this book. BALIGE Publishing has endeavored to
provide trademark information about all of the companies and products mentioned in this
book by the appropriate use of capitals. However, BALIGE Publishing cannot guarantee
the accuracy of this information.
Copyright © 2023 BALIGE Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system,
or transmitted in any form or by any means, without the prior written permission of the
publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the
information presented. However, the information contained in this book is sold without
warranty, either express or implied. Neither the authors, nor BALIGE Publishing or its
dealers and distributors, will be held liable for any damages caused or alleged to have
been caused directly or indirectly by this book. BALIGE Publishing has endeavored to
provide trademark information about all of the companies and products mentioned in this
book by the appropriate use of capitals. However, BALIGE Publishing cannot guarantee
the accuracy of this information.

Published: MAY 2023


Production reference: 01050223
Published by BALIGE Publishing Ltd.
BALIGE, North Sumatera

ABOUT THE AUTHOR


ABOUT THE AUTHOR
Vivian Siahaan is a fast-learner who likes to do new things. She was born, raised in
Hinalang Bagasan, Balige, on the banks of Lake Toba, and completed high school
education from SMAN 1 Balige. She started herself learning Java, Android,
JavaScript, CSS, C ++, Python, R, Visual Basic, Visual C #, MATLAB,
Mathematica, PHP, JSP, MySQL, SQL Server, Oracle, Access, and other
programming languages. She studied programming from scratch, starting with the most basic
syntax and logic, by building several simple and applicable GUI applications. Animation and
games are fields of programming that are interests that she always wants to develop. Besides
studying mathematical logic and programming, the author also has the pleasure of reading
novels. Vivian Siahaan has written dozens of ebooks that have been published on Sparta
Publisher: Data Structure with Java; Java Programming: Cookbook; C ++ Programming:
Cookbook; C Programming For High Schools / Vocational Schools and Students; Java
Programming for SMA / SMK; Java Tutorial: GUI, Graphics and Animation; Visual Basic
Programming: From A to Z; Java Programming for Animation and Games; C # Programming
for SMA / SMK and Students; MATLAB For Students and Researchers; Graphics in
JavaScript: Quick Learning Series; JavaScript Image Processing Methods: From A to Z; Java
GUI Case Study: AWT & Swing; Basic CSS and JavaScript; PHP / MySQL Programming:
Cookbook; Visual Basic: Cookbook; C ++ Programming for High Schools / Vocational
Schools and Students; Concepts and Practices of C ++; PHP / MySQL For Students; C #
Programming: From A to Z; Visual Basic for SMA / SMK and Students; C # .NET and SQL
Server for High School / Vocational School and Students. At the ANDI Yogyakarta publisher,
Vivian Siahaan also wrote a number of books including: Python Programming Theory and
Practice; Python GUI Programming; Python GUI and Database; Build From Zero School
Database Management System In Python / MySQL; Database Management System in Python
/ MySQL; Python / MySQL For Management Systems of Criminal Track Record Database;
Java / MySQL For Management Systems of Criminal Track Records Database; Database and
Cryptography Using Java / MySQL; Build From Zero School Database Management System
With Java / MySQL.

Rismon Hasiholan Sianipar was born in Pematang Siantar, in 1994. After

graduating from SMAN 3 Pematang Siantar 3, the writer traveled to the city of

Jogjakarta. In 1998 and 2001 the author completed his Bachelor of Engineering

(S.T) and Master of Engineering (M.T) education in the Electrical Engineering of Gadjah

Mada University, under the guidance of Prof. Dr. Adhi Soesanto and Prof. Dr. Thomas Sri

Widodo, focusing on research on non-stationary signals by analyzing their energy using time-

frequency maps. Because of its non-stationary nature, the distribution of signal energy

becomes very dynamic on a time-frequency map. By mapping the distribution of energy in the

time-frequency field using discrete wavelet transformations, one can design non-linear filters

so that they can analyze the pattern of the data contained in it. In 2003, the author received a

Monbukagakusho scholarship from the Japanese Government. In 2005 and 2008, he

completed his Master of Engineering (M.Eng) and Doctor of Engineering (Dr.Eng) education

at Yamaguchi University, under the guidance of Prof. Dr. Hidetoshi Miike. Both the master's

thesis and his doctoral thesis, R.H. Sianipar combines SR-FHN (Stochastic Resonance

Fitzhugh-Nagumo) filter strength with cryptosystem ECC (elliptic curve cryptography) 4096-

bit both to suppress noise in digital images and digital video and maintain its authenticity. The

results of this study have been documented in international scientific journals and officially
patented in Japan. One of the patents was published in Japan with a registration number 2008-

009549. He is active in collaborating with several universities and research institutions in

Japan, particularly in the fields of cryptography, cryptanalysis and audio / image / video digital

forensics. R.H. Sianipar also has experience in conducting code-breaking methods

(cryptanalysis) on a number of intelligence data that are the object of research studies in

Japan. R.H. Sianipar has a number of Japanese patents, and has written a number of national /

international scientific articles, and dozens of national books. R.H. Sianipar has also

participated in a number of workshops related to cryptography, cryptanalysis, digital

watermarking, and digital forensics. In a number of workshops, R.H. Sianipar helps Prof.

Hidetoshi Miike to create applications related to digital image / video processing,

steganography, cryptography, watermarking, non-linear screening, intelligent descriptor-based

computer vision, and others, which are used as training materials. Field of interest in the study

of R.H. Sianipar is multimedia security, signal processing / digital image / video,

cryptography, digital communication, digital forensics, and data compression / coding. Until

now, R.H. Sianipar continues to develop applications related to analysis of signal, image, and

digital video, both for research purposes and for commercial purposes based on the Python

programming language, MATLAB, C ++, C, VB.NET, C # .NET, R, and Java.

ABOUT THE BOOK

This book uses the Sakila sample database which is a


fictitious database designed to represent a DVD rental
store. The 15 tables of the database include film,
film_category, actor, customer, rental, payment and
inventory among others. The Sakila sample database is
intended to provide a standard schema that can be used
for examples in books, tutorials, articles, samples, and
so forth. You can download the sample database from
http://viviansiahaan.blogspot.com/2023/04/data-
science-using-jdbc-and-mysql-with.html.

In this project, you will design the form for every table
and you will plot: top 10 film distribution by release
year; top 10 film distribution by rating; top 10 film
distribution by rental duration; top 10 film distribution
by language; film distribution by categorized rental
rate; film distribution by categorized length; film
distribution by categorized replacement cost; top 10
film distribution by actor name; top 10 actor name
distribution by average rental rate; top 10 actor name
distribution by average replacement cost; film
distribution by rating; rating distribution by average
rental rate; rating distribution by average replacement
cost; top 10 film distribution by category name,
category distribution by average replacement cost;
category distribution by average rental rate; category
distribution by length; top 10 city distribution by by
country; top 10 address distribution by district, top 10
address distribution by country; top 10 address
distribution by city; top 10 address distribution by
district; top 10 address distribution by country; top
10 address distribution by city; top 10 inventory
distribution by release year; top 10 inventory
distribution by film rating; top 10 inventory
distribution by film language; top 10 inventory
distribution by film rental duration; top 10 inventory
distribution by city; top 10 inventory distribution by
country; top 10 customer distribution by country; top
10 customer distribution by city; top 10 customer
distribution by district; top 10 customer distribution
by store country; top 10 customer distribution by store
city; top 10 customer distribution by store district; top
10 staff distribution by country; top 10 staff
distribution by city; rental distribution by year of
rental date; rental distribution by month of rental date;
10 rental distribution by week of rental date; rental
distribution by day of rental date; rental distribution
by quarter of rental date; rental distribution by film
release year; rental distribution by film duration;
rental distribution by film rating; top 10 rental
distribution by staff name; rental distribution by film
language; top 10 rental distribution by film title;
rental distribution by customer active; top 10 rental
distribution by film category; top 10 rental distribution
by actor name; top 10 rental distribution by customer
name; top 10 rental distribution by customer city; top
10 rental distribution by customer country, top 10
rental distribution by customer district; payment
distribution by year of payment date; payment
distribution by month of payment date; top 10
payment distribution by week of payment date;
payment distribution by day of payment date;
payment distribution by quarter of payment date;
payment distribution by film release year; payment
distribution by film duration; payment distribution by
film rating; top 10 payment distribution by staff
name; payment distribution by film language; top 10
payment distribution by film title; payment
distribution by customer active; top 10 payment
distribution by film category; top 10 payment
distribution by actor name; top 10 payment
distribution by customer name; top 10 payment
distribution by customer city; top 10 payment
distribution by customer country; and top 10 payment
distribution by customer district.
CONTENT
CONTENT
PROJECT AND UTILITY CLASS 1
DESCRIPTION 1
CREATING PROJECT AND UTILITY CLASS 3
SOURCE CODE 17

ACTOR FORM 26
CREATING AND POPULATING ACTOR 26
TABLE 32
DESIGNING GUI 35
POPULATING TABLE AND COMBOBOXES 38
DISPLAYING AND NAVIGATING DATA 44
ROW BY ROW 49
UPDATING RECORD 51
UPDATING RECORD DIRECTLY ON JTABLE 54
INSERTING NEW RECORD 55
DELETING RECORD
SOURCE CODE
67
67
LANGUAGE FORM 72
CREATING AND POPULATING LANGUAGE 75
TABLE 78
DESIGNING GUI 84
POPULATING TABLE AND COMBOBOXES 88
DISPLAYING AND NAVIGATING DATA 90
ROW BY ROW 93
UPDATING RECORD 94
UPDATING RECORD DIRECTLY ON JTABLE
INSERTING NEW RECORD
DELETING RECORD 106
SOURCE CODE 106
111
114
CATEGORY FORM 118
CREATING AND POPULATING CATEGORY 123
TABLE 128
DESIGNING GUI 130
POPULATING TABLE AND COMBOBOXES 133
134
DISPLAYING AND NAVIGATING DATA
ROW BY ROW
UPDATING RECORD
UPDATING RECORD DIRECTLY ON JTABLE 145
INSERTING NEW RECORD 145
DELETING RECORD 156
SOURCE CODE 158
163
171
177
FILM FORM 179
CREATING AND POPULATING FILM TABLE 182
DESIGNING GUI 183
POPULATING TABLE AND COMBOBOXES 191
DISPLAYING AND NAVIGATING DATA
ROW BY ROW
UPDATING RECORD 209
UPDATING RECORD DIRECTLY ON JTABLE 209
INSERTING NEW RECORD 217
DELETING RECORD 219
PLOTTING CHART 224
SOURCE CODE 233
238
241
FILM ACTOR FORM 242
CREATING AND POPULATING FILM 246
ACTOR TABLE
DESIGNING GUI
POPULATING TABLE AND COMBOBOXES 261
DISPLAYING AND NAVIGATING DATA 261
ROW BY ROW 269
UPDATING RECORD 272
INSERTING NEW RECORD 276
DELETING RECORD 285
PLOTTING CHART 291
SOURCE CODE 294
294
297
FILM CATEGORY FORM
CREATING AND POPULATING FILM
CATEGORY TABLE 311
DESIGNING GUI 311
POPULATING TABLE AND COMBOBOXES 317
DISPLAYING AND NAVIGATING DATA 320
ROW BY ROW 323
UPDATING RECORD 329
INSERTING NEW RECORD 334
DELETING RECORD 336
PLOTTING CHART 339
SOURCE CODE 340

COUNTRY FORM 351


CREATING AND POPULATING COUNTRY 351
TABLE 358
DESIGNING GUI 361
POPULATING TABLE AND COMBOBOXES 365
DISPLAYING AND NAVIGATING DATA 373
ROW BY ROW 377
UPDATING RECORD 380
UPDATING RECORD DIRECTLY ON JTABLE 382
INSERTING NEW RECORD 384
DELETING RECORD 385
SOURCE CODE

399
CITY FORM 399
CREATING AND POPULATING CITY TABLE 407
DESIGNING GUI 411
POPULATING TABLE AND COMBOBOXES 416
DISPLAYING AND NAVIGATING DATA 424
ROW BY ROW 429
UPDATING RECORD 431
UPDATING RECORD DIRECTLY ON JTABLE 434
INSERTING NEW RECORD 435
DELETING RECORD 437
PLOTTING CHART
SOURCE CODE
452
452
ADDRESS FORM 460
464
CREATING AND POPULATING ADDRESS 468
TABLE 476
DESIGNING GUI 481
POPULATING TABLE AND COMBOBOXES 483
DISPLAYING AND NAVIGATING DATA 486
ROW BY ROW 487
UPDATING RECORD 489
UPDATING RECORD DIRECTLY ON JTABLE
INSERTING NEW RECORD
DELETING RECORD 504
PLOTTING CHART 504
SOURCE CODE 514
519
523
STORE FORM 533
CREATING AND POPULATING STORE 538
TABLE 541
DESIGNING GUI 542
POPULATING TABLE AND COMBOBOXES 545
DISPLAYING AND NAVIGATING DATA
ROW BY ROW
UPDATING RECORD 562
UPDATING RECORD DIRECTLY ON JTABLE 562
INSERTING NEW RECORD 572
DELETING RECORD 576
PLOTTING CHART 580
SOURCE CODE 590
596
599
INVENTORY FORM 602
CREATING AND POPULATING INVENTORY 603
TABLE 606
DESIGNING GUI
POPULATING TABLE AND COMBOBOXES
DISPLAYING AND NAVIGATING DATA 626
ROW BY ROW 626
UPDATING RECORD 635
INSERTING NEW RECORD 639
DELETING RECORD 643
PLOTTING CHART 655
SOURCE CODE 659
663
664
CUSTOMER FORM 666
CREATING AND POPULATING CUSTOMER
TABLE
DESIGNING GUI 685
POPULATING TABLE AND COMBOBOXES 685
DISPLAYING AND NAVIGATING DATA 697
ROW BY ROW 703
UPDATING RECORD 707
UPDATING RECORD DIRECTLY ON JTABLE 719
INSERTING NEW RECORD 725
DELETING RECORD 728
PLOTTING CHART 729
SOURCE CODE 738

STAFF FORM 762


CREATING AND POPULATING STAFF 762
TABLE 774
DESIGNING GUI 780
POPULATING TABLE AND COMBOBOXES 784
DISPLAYING AND NAVIGATING DATA 796
ROW BY ROW 802
UPDATING RECORD 805
INSERTING NEW RECORD 806
DELETING RECORD 816
PLOTTING CHART
SOURCE CODE
840
840
RENTAL FORM
CREATING AND POPULATING RENTAL
TABLE
DESIGNING GUI
POPULATING TABLE AND COMBOBOXES
DISPLAYING AND NAVIGATING DATA
ROW BY ROW
UPDATING RECORD
INSERTING NEW RECORD
DELETING RECORD
PLOTTING CHART
SOURCE CODE

PAYMENT FORM
CREATING AND POPULATING PAYMENT
TABLE
DESIGNING GUI
POPULATING TABLE AND COMBOBOXES
DISPLAYING AND NAVIGATING DATA
ROW BY ROW
UPDATING RECORD
INSERTING NEW RECORD
DELETING RECORD
PLOTTING CHART
SOURCE CODE

MAIN FORM
DESIGNING GUI

PROJECT
AND UTILITY CLASS
PROJECT
AND UTILITY CLASS
DESCRIPTION
DESCRIPTION

This book uses the Sakila sample database which is a


fictitious database designed to represent a DVD
rental store. The tables of the database include film,
film_category, actor, customer, rental, payment and
inventory among others. The Sakila sample database
is intended to provide a standard schema that can be
used for examples in books, tutorials, articles,
samples, and so forth. You can download the sample
database from
http://viviansiahaan.blogspot.com/2023/04/data-
science-using-jdbc-and-mysql-with.html.

In this project, you will design the form for every


table and you will plot: top 10 film distribution by
release year; top 10 film distribution by rating; top 10
film distribution by rental duration; top 10 film
distribution by language; film distribution by
categorized rental rate; film distribution by
categorized length; film distribution by categorized
replacement cost; top 10 film distribution by actor
name; top 10 actor name distribution by average
rental rate; top 10 actor name distribution by average
replacement cost; film distribution by rating; rating
distribution by average rental rate; rating distribution
by average replacement cost; top 10 film distribution
by category name, category distribution by average
replacement cost; category distribution by average
rental rate; category distribution by length; top 10
city distribution by by country; top 10 address
distribution by district, top 10 address distribution
by country; top 10 address distribution by city; top
10 address distribution by district; top 10 address
distribution by country; top 10 address distribution
by city; top 10 inventory distribution by release year;
top 10 inventory distribution by film rating; top 10
inventory distribution by film language; top 10
inventory distribution by film rental duration; top 10
inventory distribution by city; top 10 inventory
distribution by country; top 10 customer distribution
by country; top 10 customer distribution by city; top
10 customer distribution by district; top 10 customer
distribution by store country; top 10 customer
distribution by store city; top 10 customer
distribution by store district; top 10 staff distribution
by country; top 10 staff distribution by city; rental
distribution by year of rental date; rental distribution
by month of rental date; 10 rental distribution by
week of rental date; rental distribution by day of
rental date; rental distribution by quarter of rental
date; rental distribution by film release year; rental
distribution by film duration; rental distribution by
film rating; top 10 rental distribution by staff name;
rental distribution by film language; top 10 rental
distribution by film title; rental distribution by
customer active; top 10 rental distribution by film
category; top 10 rental distribution by actor name;
top 10 rental distribution by customer name; top 10
rental distribution by customer city; top 10 rental
distribution by customer country, top 10 rental
distribution by customer district; payment
distribution by year of payment date; payment
distribution by month of payment date; top 10
payment distribution by week of payment date;
payment distribution by day of payment date;
payment distribution by quarter of payment date;
payment distribution by film release year; payment
distribution by film duration; payment distribution
by film rating; top 10 payment distribution by staff
name; payment distribution by film language; top
10 payment distribution by film title; payment
distribution by customer active; top 10 payment
distribution by film category; top 10 payment
distribution by actor name; top 10 payment
distribution by customer name; top 10 payment
distribution by customer city; top 10 payment
distribution by customer country; and top 10
payment distribution by customer district.

The Sakila sample database includes 15 tables and


the table relationships are showcased in the following
entity relationship diagram.

Figure 1 The ERD of Sakila database

CREATING PROJECT AND UTILITY CLASS


CREATING PROJECT AND UTILITY CLASS

Step Create a new MySQL database named Sakila using phpMyAdmin.


1
Step In NetBeans, create a new project named Sakila. Add jcommon.jar, jfreec
2 jcalendar.jar, and mysql-connector-java.jar files into the libraries in your project
Step Add a new properties file into the project. Right click on the project, choose New >
3 Other > Properties File. Click Next, and set its file name as database. Set the u
user, and password of yours as follows:

1 url =
2 jdbc:mysql://localhost:3306/sakila
3 user = vivian
password = vivian

Step Then, create a public class named Utility. Define two new methods: getConnect
4 testConnection().

The getConnection() method is responsible for creating a connection to the datab


the properties specified in the database.properties file. It reads these properties from
using a FileInputStream and a Properties object. The method then uses these pro
create a Connection object using the DriverManager class. If there is an error re
file or creating the connection, the method logs a SEVERE level message with th
object and returns null.

The testConnection() method is responsible for testing the database connection. It


by calling getConnection() and attempting to create a connection to the databa
connection is successful, it logs an INFO level message with the Logger object i
that the connection was successful. If there is an error creating the connection, th
logs a SEVERE level message with the Logger object.

1 package Sakila;
2 import java.io.FileInputStream;
3 import java.sql.Connection;
4 import java.sql.DriverManager;
5 import java.sql.SQLException;
6 import java.util.Properties;
7 import java.util.logging.Level;
8 import java.util.logging.Logger;
9 import java.sql.*;
10 import java.awt.BorderLayout;
11 import java.awt.Color;
12 import java.awt.Component;
13 import java.awt.RenderingHints;
14 import java.awt.image.BufferedImage;
15 import java.io.File;
16 import java.io.IOException;
17 import javax.swing.JOptionPane;
18 import java.text.DecimalFormat;
19 import java.text.NumberFormat;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Objects;
25 import javax.imageio.ImageIO;
26 import javax.swing.ImageIcon;
27 import javax.swing.JComboBox;
28 import javax.swing.JFileChooser;
29 import javax.swing.JFrame;
30 import javax.swing.JLabel;
31 import javax.swing.JPanel;
32 import javax.swing.JTable;
33 import javax.swing.JTextField;
34 import javax.swing.SwingUtilities;
35 import javax.swing.UIManager;
36 import javax.swing.UnsupportedLookAndFeelException;
37 import javax.swing.plaf.nimbus.NimbusLookAndFeel;
38 import javax.swing.table.DefaultTableCellRenderer;
39 import javax.swing.table.TableCellRenderer;
40 import javax.swing.table.TableColumn;
41 import org.jfree.chart.ChartFactory;
42 import org.jfree.chart.ChartPanel;
43 import org.jfree.chart.JFreeChart;
44 import org.jfree.chart.labels.ItemLabelAnchor;
45 import org.jfree.chart.labels.ItemLabelPosition;
46 import
47 org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
48 import
49 org.jfree.chart.labels.StandardPieSectionLabelGenerator;
50 import org.jfree.chart.plot.CategoryPlot;
51 import org.jfree.chart.plot.PiePlot;
52 import org.jfree.chart.plot.PlotOrientation;
53 import
54 org.jfree.chart.renderer.category.CategoryItemRenderer;
55 import org.jfree.chart.ui.TextAnchor;
56 import org.jfree.data.category.DefaultCategoryDataset;
57 import org.jfree.data.general.DefaultPieDataset;
58
59 public class Utility {
60 private static final Logger LOGGER =
61 Logger.getLogger(Utility.class.getName());
62
63
64 public static Connection getConnection() throws
65 SQLException {
66 Connection conn = null;
67 Properties props = new Properties();
68 try (FileInputStream fis = new
69 FileInputStream("database.properties")) {
70 props.load(fis);
71 String url = props.getProperty("url");
72 String user = props.getProperty("user");
73 String password =
74 props.getProperty("password");
75
76 conn = DriverManager.getConnection(url, user,
77 password);
78 } catch (IOException ex) {
79 LOGGER.log(Level.SEVERE, null, ex);
80 }
81 return conn;
82 }
83
84 public static void testConnection() {
85 try (Connection conn = getConnection()) {
String message = String.format("Successfully
connected to %s database", conn.getCatalog());
LOGGER.log(Level.INFO, message);
} catch (SQLException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
}

Step In Utility class, define a new method named populate_combobox(). It tak


5 parameters:
sql: the SQL statement to execute in order to retrieve data for populating th
box.
jcb: the JComboBox object that will be populated with the retrieved data.
obj_form: the parent JFrame object.
The method first removes all items from the combo box using the jcb.removeA
method. Then it creates a ResultSet object by executing the SQL que
getConnection() method.

Next, the method loops through the ResultSet and retrieves the first column's value
row, casts it to a generic type T, and adds it to the combo box using the jcb.a
method. Finally, the method closes the ResultSet.

If any SQL exception is thrown, the method displays an error message dialog box
exception message.

1 public static <T> void


2 populate_combobox(String sql,
3 JComboBox<T> jcb, JFrame obj_form) {
4 ResultSet rs = null;
5 jcb.removeAllItems();
6 try (Connection conn =
7 getConnection()) {
8 Statement st =
9 conn.createStatement();
10 rs = st.executeQuery(sql);
11
12 while (rs.next()) {
13 T value = (T)
14 rs.getObject(1);
15 jcb.addItem(value);
16 }
17
18 } catch (SQLException ex) {
19
20 JOptionPane.showMessageDialog(obj_form,
21 ex.getMessage(),
22 "ERROR",
23 JOptionPane.ERROR_MESSAGE);
24 } finally {
25 try {
if (rs != null)
rs.close();
} catch (SQLException ex) {

JOptionPane.showMessageDialog(obj_form,
ex.getMessage(),
"ERROR",
JOptionPane.ERROR_MESSAGE);
}
}
}

Step Then, add a new method named table_renderer(). This method is used to custo
6 rendering of a JTable object. The method takes a JTable object as its input param
sets the default cell renderer of the JTable object to a custom renderer. The custom
overrides the getTableCellRendererComponent() method of the TableCellR
interface, and sets the background color of alternate rows to white and light gray, t
easier to read the data in the table.

The method achieves this by creating a new TableCellRenderer object and over
getTableCellRendererComponent() method. The method checks if the row n
even or odd, and sets the background color of the cell accordingly. If the row n
even, the background color is set to white, and if the row number is odd, the ba
color is set to light gray. The method returns the component with the updated ba
color.

This method can be called after populating a JTable object to apply the cus
rendering.

1 public static void table_renderer(JTable jtable)


2 {
3 jtable.setDefaultRenderer(Object.class,
4 new TableCellRenderer(){
5 private DefaultTableCellRenderer
6 DEFAULT_RENDERER = new DefaultTableCellRenderer();
7 @Override
8 public Component
9 getTableCellRendererComponent(JTable table,
10 Object value, boolean isSelected, boolean
11 hasFocus, int row, int column) {
12 Component c =
13 DEFAULT_RENDERER.getTableCellRendererComponent(table,
14 value, isSelected, hasFocus, row,
15 column);
16 if (row%2 == 0){
17 c.setBackground(Color.WHITE);
18 }
19 else {
20
21 c.setBackground(Color.LIGHT_GRAY);
22 }
return c;
}
});
}

Step Then, add a new method named set_column_header(). This method sets the colum
7 for a JTable. The method takes two arguments: the JTable object and a Stri
containing the column headers.
The method loops through the columns of the table using a for loop and gets th
model of the table header for each column using the getColumnModel() method
sets the header value of each column using the setHeaderValue() method
corresponding value from the header array.

Finally, the method returns the same header array that was passed as input argumen

1 //Sets columns header


2 public static String[] set_column_header(JTable
3 table, String header[]) {
4 for(int i=0;i<table.getColumnCount();i++)
5 {
6 TableColumn cols =
7 table.getTableHeader().getColumnModel().getColumn(i);
8 cols.setHeaderValue(header[i]);
9 }
10 return header;
}
Step Still in Utility class, add a new method named find_combo_value_selected(). Thi
8 is used to find the selected item in a JComboBox and set it to the specified value if
It takes two parameters, the JComboBox and the value to search for.

It first sets a boolean variable found to false to indicate that the specified value ha
been found. Then it iterates over each item in the JComboBox using a for loop.

Inside the loop, it retrieves the item at the current index and compares it to the
value using the Objects.equals() method. If the item matches the specified value, i
selected index of the JComboBox to the current index and sets found to true to ind
the value was found. It then breaks out of the loop since there is no need to
iterating.

If the specified value is not found in the JComboBox, it sets the selected index
indicate that no item is selected.

1 //Finds selected item in combobox


2 public static <T> void
3 find_combo_value_selected(JComboBox<T>
4 comboBox, T value) {
5 boolean found = false;
6 for (int i = 0; i <
7 comboBox.getItemCount(); i++) {
8 T item =
9 comboBox.getItemAt(i);
10 if (Objects.equals(item,
11 value)) {
12
13 comboBox.setSelectedIndex(i);
14 found = true;
15 break;
16 }
}
if (!found) {

comboBox.setSelectedIndex(-1);
}
}

Step Then, add a new method named item_to_display(). This method is used to ha
9 pagination of data displayed in a form. It takes in the SQL statements for ge
minimum and maximum values of the data, a text field where the current page n
displayed, and a string indicating the direction of pagination (first, previous, next, la
The method first checks if the text field is empty or null. If it is, it returns the def
number of 1. Otherwise, it tries to parse the integer value of the text field and sets t
current page number. If the parsing fails due to an invalid integer format, an error
is displayed and the default page number is returned.

Depending on the direction of pagination, the method executes the correspond


statement to get the minimum and maximum values of the data, and then updates th
page number accordingly. If the direction is "first", it sets the current page numb
minimum value. If it is "prev", it decrements the current page number by 1, or set
maximum value if it is already 1. If it is "next", it increments the current page num
or sets it to 1 if it is already at the maximum value. If it is "last", it sets the curr
number to the maximum value.

If any errors occur during the SQL execution, an error message is displayed. Th
then returns the updated current page number.

1 public static int


2 item_to_display(JFrame frm, String
3 sql_min, String sql_max, JTextField
4 jtf, String direction) {
5 int currentValue = 1;
6
7 String text = jtf.getText();
8 if (text == null ||
9 text.trim().isEmpty()) {
10 return currentValue;
11 }
12
13 try {
14 currentValue =
15 Integer.parseInt(text);
16 } catch (NumberFormatException
17 ex) {
18
19 JOptionPane.showMessageDialog(frm,
20 ex.getMessage(), "ERROR",
21 JOptionPane.ERROR_MESSAGE);
22 return currentValue;
23 }
24
25 switch (direction) {
26 case "first":
27 try (Connection conn =
28 getConnection();
29 PreparedStatement
30 ps = conn.prepareStatement(sql_min)) {
31 ResultSet rs =
32 ps.executeQuery();
33 if (rs.next()) {
34
35 currentValue =
36 rs.getInt(1);
37 }
38 } catch (SQLException
39 ex) {
40
41 JOptionPane.showMessageDialog(frm,
42 ex.getMessage(),
43 "ERROR",
44 JOptionPane.ERROR_MESSAGE);
45
46 }catch(java.lang.NumberFormatException
47 ex){
48
49 JOptionPane.showMessageDialog(frm,
50 ex.getMessage(),
51
52 "ERROR",JOptionPane.ERROR_MESSAGE);
53 }
54 break;
55
56 case "prev":
57 try (Connection conn =
58 getConnection();
59 PreparedStatement
60 ps = conn.prepareStatement(sql_max)) {
61 ResultSet rs =
62 ps.executeQuery();
63 if (rs.next()) {
64 int max =
65 rs.getInt(1);
66 if
67 (currentValue > 1) {
68
69 currentValue--;
70 } else {
71
72 currentValue = max;
73 }
74 }
75 } catch (SQLException
76 ex) {
77
78 JOptionPane.showMessageDialog(frm,
79 ex.getMessage(),
80 "ERROR",
81 JOptionPane.ERROR_MESSAGE);
82
83 }catch(java.lang.NumberFormatException
84 ex){
85
86 JOptionPane.showMessageDialog(frm,
87 ex.getMessage(),
88
89 "ERROR",JOptionPane.ERROR_MESSAGE);
90 }
91 break;
92
93 case "next":
94 try (Connection conn =
95 getConnection();
96 PreparedStatement
ps = conn.prepareStatement(sql_max)) {
ResultSet rs =
ps.executeQuery();
if (rs.next()) {
int max =
rs.getInt(1);
if
(currentValue < max) {

currentValue++;
} else {

currentValue = 1;
}
}
} catch (SQLException
ex) {

JOptionPane.showMessageDialog(frm,
ex.getMessage(),
"ERROR",
JOptionPane.ERROR_MESSAGE);

}catch(java.lang.NumberFormatException
ex){

JOptionPane.showMessageDialog(frm,
ex.getMessage(),

"ERROR",JOptionPane.ERROR_MESSAGE);
}
break;

case "last":
try (Connection conn =
getConnection();
PreparedStatement
ps = conn.prepareStatement(sql_max)) {
ResultSet rs =
ps.executeQuery();
if (rs.next()) {
currentValue =
rs.getInt(1);
}
} catch (SQLException
ex) {

JOptionPane.showMessageDialog(frm,
ex.getMessage(),
"ERROR",
JOptionPane.ERROR_MESSAGE);

}catch(java.lang.NumberFormatException
ex){

JOptionPane.showMessageDialog(frm,
ex.getMessage(),

"ERROR",JOptionPane.ERROR_MESSAGE);
}
break;
default:
break;
}
return currentValue;
}

Step Then, add a new method named setLookAndFeel().This method sets the look and
10 JFrame to the Nimbus look and feel, and then customizes the colors of va
elements. The Nimbus look and feel is a cross-platform look and feel that was intro
Java 6.

The method first sets the Nimbus look and feel using UIManager.setLookAnd
then sets various UI colors using UIManager.put(). Finally, it updates the U
JFrame using SwingUtilities.updateComponentTreeUI().

1 public static void


2 setLookAndFeel(JFrame frame) {
3 try {
4 // Set the Nimbus look and feel
5 UIManager.setLookAndFeel(new
6 NimbusLookAndFeel());
7
8 // Set the UI colors
9 UIManager.put("control", new
10 Color(240, 240, 240));
11 UIManager.put("info", new
12 Color(128, 128, 128));
13 UIManager.put("text", new
14 Color(50, 50, 50));
15 UIManager.put("nimbusBase", new
16 Color(250, 30, 49));
17
18 UIManager.put("nimbusAlertYellow", new
19 Color(248, 187, 0));
20
21 UIManager.put("nimbusDisabledText", new
22 Color(128, 128, 128));
23
24 UIManager.put("nimbusFocus",
25 new Color(115, 164, 209));
26 UIManager.put("nimbusGreen",
27 new Color(176, 179, 50));
UIManager.put("nimbusInfoBlue",
new Color(66, 139, 221));

UIManager.put("nimbusLightBackground", new
Color(220, 220, 220));
UIManager.put("nimbusOrange",
new Color(191, 98, 4));
UIManager.put("nimbusRed", new
Color(169, 46, 34));

UIManager.put("nimbusSelectedText", new
Color(255, 255, 255));

UIManager.put("nimbusSelectionBackground",
new Color(104, 93, 156));

// Update the UI for the JFrame

SwingUtilities.updateComponentTreeUI(frame);
} catch
(UnsupportedLookAndFeelException e) {
System.err.println("Nimbus:
Unsupported Look and feel!");
}
}

Step Then, add two new methods named create_pie_dataset_from_categorized_va


11 create_bar_dataset_from_categorized_vals().

These are two utility methods for creating datasets for pie charts and ba
respectively. Both methods take a Map<String, Double> object, where each key r
a category and its associated value is the count for that category.

The create_pie_dataset_from_categorized_vals() creates a DefaultPieData


populates it with the category names and counts from the input map.

The create_bar_dataset_from_categorized_vals() creates a DefaultCategoryDa


populates it with the category names and counts from the input map, with "Coun
series name for all categories.

1 public static DefaultPieDataset


2 create_pie_dataset_from_categorized_vals(Map<String,
3 Double> count_map) {
4
5 DefaultPieDataset dataset = new
6 DefaultPieDataset();
7 count_map.forEach((key, value) ->
8 dataset.setValue(key, value));
9 return dataset;
10 }
11
12 public static DefaultCategoryDataset
13 create_bar_dataset_from_categorized_vals(Map<String,
14 Double> count_map) {
15 DefaultCategoryDataset dataset = new
DefaultCategoryDataset();
for (Map.Entry<String, Double> entry :
count_map.entrySet()) {
dataset.addValue(entry.getValue(),
"Count", entry.getKey());
}
return dataset;
}

Step Define two new methods named draw_barchart_with_dataset(


12 draw_piechart_with_dataset(). These two methods create and display bar and p
respectively, using the JFreeChart library.

The draw_barchart_with_dataset() method takes in a JFrame object, a JPanel


DefaultCategoryDataset object, chart title, x-axis label and y-axis label as param
removes all components from the JPanel, creates a JFreeChart object with t
parameters, sets its background color and creates a ChartPanel object with t
Finally, it adds the chart to the JPanel and validates it.

The draw_piechart_with_dataset() method is similar, but it takes in a DefaultPi


object and a chart title as parameters. It creates a JFreeChart object with t
parameters, sets its background color and label generator to show percentages,
ChartPanel object with the chart, and adds it to the JPanel. Finally, it validates the

Both methods catch any exceptions that may occur and display an error message in
box if necessary.

1 public static void draw_barchart_with_dataset(JFrame frm, JPanel


2 DefaultCategoryDataset dataset,
3 String title, String xlabel, String ylabel){
4 jp.removeAll();
5
6 try{
7 //Creates a JFreeChart object
8 JFreeChart chartBar = ChartFactory.createBarChart(
9 title, // chart title
10 xlabel, // x-axis label
11 ylabel, // y-axis label
12 dataset, // dataset
13 PlotOrientation.HORIZONTAL, // orientation
14 false, // include legend
15 true, // tooltips
16 false // urls
17 );
18
19
20 chartBar.getRenderingHints().put(JFreeChart.KEY_SUPPRESS_SHADOW_GENE
21 Boolean.TRUE);
22
23 chartBar.getRenderingHints().put(RenderingHints.KEY_ANTIALIASING,
24 RenderingHints.VALUE_ANTIALIAS_ON);
25
26 //Sets background color 150
27 chartBar.setBackgroundPaint(new Color(200,250,200));
28 chartBar.getPlot().setBackgroundPaint(new Color(200, 216
29 250));
30
31 //Create a ChartPanel object
32 ChartPanel barchartPanel = new ChartPanel(chartBar);
33 jp.setLayout(new java.awt.BorderLayout());
34 jp.add(barchartPanel, BorderLayout.CENTER);
35
36 jp.validate();
37 }
38 catch (Exception ex){
39 JOptionPane.showMessageDialog(frm, ex.getMessage(),
40 "ERROR",JOptionPane.ERROR_MESSAGE);
41 }
42 }
43
44 public static void draw_piechart_with_dataset(JFrame frm, JPanel
45 DefaultPieDataset dataset, String title){
46 jp.removeAll();
47
48 try{
49 //Creates a JFreeChart object
50 JFreeChart chartPie = ChartFactory.createPieChart(
51 title, // chart title
52 dataset, // dataset
53 true, // include legend
54 true, // tooltips
55 false // urls
56 );
57
58 //Sets background color
59 chartPie.getPlot().setBackgroundPaint(new Color(150,200,
60
61
62 // Sets the label generator to show percentages
63 PiePlot plot = (PiePlot) chartPie.getPlot();
64 plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0} ({
65
66
67 NumberFormat.getNumberInstance(), new DecimalFormat("0.0%")));
68 //Create a ChartPanel object
69 ChartPanel piechartPanel = new ChartPanel(chartPie);
70 jp.setLayout(new java.awt.BorderLayout());
71 jp.add(piechartPanel, BorderLayout.CENTER);
72 jp.validate();
73 }
74 catch (Exception ex){
75 JOptionPane.showMessageDialog(frm, ex.getMessage(),
"ERROR",JOptionPane.ERROR_MESSAGE);
}
}

Step Define two new methods named get_col_val_from_database(


13 get_val_from_database().
The get_col_val_from_database() takes two parameters, the column and table na
returns a list of values from the specified column in the specified table. It uses a
statement to retrieve the data and then iterates through the ResultSet to add the
values to the list. It uses a generic type T to allow the method to return a list of any

The get_val_from_database takes() four parameters: tableName, colum


condition, and item. It retrieves a single value from a table where the specified
matches the item value. It uses a PreparedStatement with a SELECT statem
includes a WHERE clause to retrieve the data. The method sets the item va
parameter in the prepared statement and then retrieves the result using a Resu
returns the result object or null if no matching row is found.

1 public static <T> List<T>


2 get_col_val_from_database(String
3 column, String table) throws
4 SQLException,
5 ClassNotFoundException {
6 List<T> values = new
7 ArrayList<>();
8 String query = "SELECT " +
9 column + " FROM " + table;
10
11 try(Connection conn =
12 getConnection();
13 Statement statement =
14 conn.createStatement();
15 ResultSet resultSet
16 = statement.executeQuery(query)){
17
18 // Iterates through the
19
result set and add the column values to the
20
21 list
22 while
23 (resultSet.next()) {
24 T value = (T)
25 resultSet.getObject(column);
26 values.add(value);
27 }
28 }catch (SQLException ex){
29
30 JOptionPane.showMessageDialog(null,
31 ex.getMessage(),
32
33 "ERROR",JOptionPane.ERROR_MESSAGE);
34 }
35 return values;
36 }
37
38
39 public static Object
40 get_val_from_database(String
41 tableName, String columnName,
42 String condition, Object item) {
43 Object result = null;
44 String query = "SELECT " +
45 columnName + " FROM " + tableName +
" WHERE " + condition + " = ?";
try (Connection conn =
getConnection();
PreparedStatement ps =
conn.prepareStatement(query)) {

ps.setObject(1, item);
try (ResultSet rs =
ps.executeQuery()) {
if (rs.next()) {
result =
rs.getObject(columnName);

} else {
// no row
found, clear the form fields

JOptionPane.showMessageDialog(null,
"ITEM NOT FOUND");
}
}
} catch (SQLException ex) {

JOptionPane.showMessageDialog(null,
ex.getMessage(), "ERROR",
JOptionPane.ERROR_MESSAGE);
}
return result;
}
Step Then, still in Utility class, define a new method named categorize_values().Thi
14 takes a list of numerical values and a map that defines the ranges for different cate
returns a map that contains the count of values that fall within each category.

The method first initializes an empty map of counts for each category using the k
the input map. Then, it loops through each value in the input list and categorizes i
corresponding range by comparing it to the values in the input map. If the value fa
a range, the corresponding category is set for that value. Finally, the count
corresponding category is incremented in the counts map.

The method returns the counts map, which contains the count of values for each
The key of the map represents the category, and the value represents the count of v
fall within that category.

1 public static Map<String, Double>


2 categorize_values(List<? extends
3 Number> list_vals, Map<String, ?
4 extends Number> range_vals) {
5 Map<String, Double> counts =
6 new HashMap<>();
7
8 // Initialize the counts map
9 for (String category :
10 range_vals.keySet()) {
11 counts.put(category, 0.0);
12 }
13
14
15 // Loop through list_vals and
16 categorize them into their
17 corresponding range
18 for (Number val : list_vals) {
19 double dbValue =
20 val.doubleValue();
21 String category =
22 range_vals.keySet().iterator().next();
23 // Default category
24
25 for (Map.Entry<String, ?
26 extends Number> range :
27 range_vals.entrySet()) {
28 if (dbValue <
29 range.getValue().doubleValue()) {
30 category =
31 range.getKey();
32 break;
33 }
}
// Increment the count for
the corresponding category
Double countObj =
counts.get(category);
double count = countObj !=
null ? countObj.doubleValue() : 0;
counts.put(category, count
+ 1);
}

return counts;
}

Step Define two new methods named create_bar_dataset() and create_pie_dataset(). T


15 two utility methods that create a bar chart dataset and a pie chart dataset from the
an SQL query. Both methods take in a query string, a column name for the valu
column name for the labels.

The create_bar_dataset() method uses a DefaultCategoryDataset object and ad


to it using the addValue() method. The labels for the x-axis are added as th
parameter to this method, and the label for each data point is added as the third para

The create_pie_dataset() method uses a DefaultPieDataset object and adds va


using the setValue() method. The label for each data point is added as the first p
and the value is added as the second parameter.

Both methods handle values of different types (String or Number) by checking th


the value and parsing it as a double if necessary. If the value is neither a Stri
Number, a RuntimeException is thrown.

Both methods also catch any exceptions that occur during the execution of the SQ
and display an error message using a JOptionPane.

1 public static
2 DefaultCategoryDataset
3 create_bar_dataset(String query,
4 String valColumn, String
5 labelColumn){
6 // Creates a
7 DefaultCategoryDataset object
8 DefaultCategoryDataset
9 dataset = new
10 DefaultCategoryDataset();
11
12 try(Connection conn =
13 getConnection(); Statement stmt =
14 conn.createStatement();
15 ResultSet rs =
16 stmt.executeQuery(query)){
17
18 while (rs.next()) {
19 Object value =
20 rs.getObject(valColumn);
21 String label =
22 rs.getString(labelColumn);
23
24 if (value
25 instanceof Number) {
26
27 dataset.addValue(((Number)
28 value).doubleValue(), labelColumn,
29 label);
30 } else if (value
31 instanceof String) {
32 double
33 doubleValue =
34 Double.parseDouble((String) value);
35
36 dataset.addValue(doubleValue,
37 labelColumn, label);
38 } else {
39 throw new
40 RuntimeException("Unsupported value
41 type: " +
42 value.getClass().getName());
43 }
44 }
45 } catch (Exception ex){
46
47 JOptionPane.showMessageDialog(null,
48 ex.getMessage(),
49
50 "ERROR",JOptionPane.ERROR_MESSAGE);
51 }
52 return dataset;
53 }
54
55 public static DefaultPieDataset
56 create_pie_dataset(String query,
57 String valColumn, String
58 labelColumn){
59 // Creates a
60 DefaultPieDataset object
61 DefaultPieDataset dataset =
new DefaultPieDataset();

try(Connection conn =
getConnection(); Statement stmt =
conn.createStatement();
ResultSet rs =
stmt.executeQuery(query)){
while (rs.next()) {
Object value =
rs.getObject(valColumn);
String label =
rs.getString(labelColumn);

if (value
instanceof Number) {

dataset.setValue(label, ((Number)
value).doubleValue());
} else if (value
instanceof String) {
double
doubleValue =
Double.parseDouble((String) value);

dataset.setValue(label,
doubleValue);
} else {
throw new
RuntimeException("Unsupported value
type: " +
value.getClass().getName());
}
}
} catch (Exception ex){

JOptionPane.showMessageDialog(null,
ex.getMessage(),

"ERROR",JOptionPane.ERROR_MESSAGE);
}
return dataset;
}

Step Then, define two new methods named read_image() and show_image(). Th
16 methods are related to displaying images on a Swing-based user interface.

The read_image() method allows the user to select an image file using the JFile
dialog box and then display it on a given JLabel control. It takes three parameters:

jframe: a JFrame instance which is used as the parent of the file choos
box
jtfPhotoPath: a JTextField instance that will display the absolute pat
selected image file
label: a JLabel instance which is used to display the selected image
The method first creates a JFileChooser object and sets the current directory to t
home directory. It then shows the dialog box and waits for the user to select a fi
user chooses a valid image file that can be read, the method reads the image file
ImageIO.read() method and displays it on the given JLabel control. It also sets th
the given JTextField control to the absolute path of the selected image file. If the
file is not a valid image file or cannot be read, the method shows an error mess
message dialog box and resets the JLabel and JTextField controls.

The show_image() method takes two parameters:


label: a JLabel instance which is used to display the image
path: a String containing the path of the image file to be displayed
This method simply loads the image from the given file path and sets it as the ic
given JLabel control using the ImageIcon class.

1 public void read_image(JFrame jframe, JTextField


2 jtfPhotoPath, JLabel label) {
3 BufferedImage im = null;
4 try {
5 JFileChooser fileChooser = new JFileChooser();
6 fileChooser.setCurrentDirectory(new
7 File(System.getProperty("user.home")));
8 int result = fileChooser.showOpenDialog(jframe);
9 if (result == JFileChooser.APPROVE_OPTION) {
10 File fileChosen = fileChooser.getSelectedFile();
11 if (fileChosen.isFile() && fileChosen.canRead())
12 {
13 im = ImageIO.read(fileChosen);
14
15 jtfPhotoPath.setText(fileChosen.getAbsolutePath());
16
17 // Display image on jLabelImage
18 ImageIcon icon = new ImageIcon(im);
19 label.setIcon(icon);
20 } else {
21 throw new IOException("Selected file is not
22 a valid image file or cannot be read.");
23 }
24 }
25 } catch (IOException e) {
26 JOptionPane.showMessageDialog(jframe, "Error reading
27 image file: " + e.getMessage(),
28 "Error", JOptionPane.ERROR_MESSAGE);
29 label.setIcon(null);
30 jtfPhotoPath.setText("");
31 } catch (Exception e) {
32 ImageIcon icon = new
33 ImageIcon(getClass().getClassLoader().getResource("dummy.png"));
34 label.setIcon(icon);
35 }
36 }
37
38 public static void show_image(JLabel label, String path) {
39 // Display image on JLabel control
ImageIcon icon = new ImageIcon(path);
label.setIcon(icon);
}

Step Next, define a new method named findMaxInt(). This method is used to find the m
17 integer value in a specific column of a MySQL table. It takes in three parame
connection object to the database, the name of the table, and the name of the c
search for the maximum value in.

Inside the method, an initial value of the maximum value is set to the smallest
integer value. The method then constructs a SQL query string to find the maximum
the specified column of the specified table. The query string is executed using a S
object, and the resulting ResultSet is processed to obtain the maximum value found

If there are no results in the ResultSet, the initial minimum value set at the sta
method is returned. Otherwise, the maximum value found in the ResultSet is return

1 public static int


2 findMaxInt(Connection conn, String
3 tableName, String columnName)
4 throws SQLException {
5 int max =
6 Integer.MIN_VALUE;
7 String query = "SELECT
8 MAX(" + columnName + ") FROM " +
9 tableName;
10 try (Statement stmt =
11 conn.createStatement();
12 ResultSet rs =
stmt.executeQuery(query)) {
if (rs.next()) {
max = rs.getInt(1);
}
}
return max;
}

Step Then, define an overloaded read_image() method with only two parameters:
18
1 public void read_image(JFrame jframe, JLabel label) {
2 BufferedImage im = null;
3 try {
4 JFileChooser fileChooser = new JFileChooser();
5 fileChooser.setCurrentDirectory(new
6 File(System.getProperty("user.home")));
7 int result = fileChooser.showOpenDialog(jframe);
8 if (result == JFileChooser.APPROVE_OPTION) {
9 File fileChosen = fileChooser.getSelectedFile();
10 if (fileChosen.isFile() && fileChosen.canRead())
11 {
12 im = ImageIO.read(fileChosen);
13
14 // Display image on jLabelImage
15 ImageIcon icon = new ImageIcon(im);
16 label.setIcon(icon);
17 } else {
18 throw new IOException("Selected file is not
19 a valid image file or cannot be read.");
20 }
21 }
22 } catch (IOException e) {
23 JOptionPane.showMessageDialog(jframe, "Error reading
24 image file: " + e.getMessage(),
25 "Error", JOptionPane.ERROR_MESSAGE);
26 label.setIcon(null);
27 } catch (Exception e) {
28 ImageIcon icon = new
29 ImageIcon(getClass().getClassLoader().getResource("dummy.png"));
30 label.setIcon(icon);
31 }
}

This is the full version of Utility.java:


package Sakila;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.sql.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.swing.JOptionPane;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import
org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import
org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PlotOrientation;
import
org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.ui.TextAnchor;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;

public class Utility {


private static final Logger LOGGER =
Logger.getLogger(Utility.class.getName());

public static Connection getConnection() throws


SQLException {
Connection conn = null;
Properties props = new Properties();
try (FileInputStream fis = new
FileInputStream("database.properties")) {
props.load(fis);
String url = props.getProperty("url");
String user = props.getProperty("user");
String password =
props.getProperty("password");
conn = DriverManager.getConnection(url, user,
password);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
return conn;
}

public static void testConnection() {


try (Connection conn = getConnection()) {
String message = String.format("Successfully
connected to %s database", conn.getCatalog());
LOGGER.log(Level.INFO, message);
} catch (SQLException ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}

public static <T> void populate_combobox(String sql,


JComboBox<T> jcb, JFrame obj_form) {
ResultSet rs = null;
jcb.removeAllItems();
try (Connection conn = getConnection()) {
Statement st = conn.createStatement();
rs = st.executeQuery(sql);

while (rs.next()) {
T value = (T) rs.getObject(1);
jcb.addItem(value);
}

} catch (SQLException ex) {


JOptionPane.showMessageDialog(obj_form,
ex.getMessage(),
"ERROR", JOptionPane.ERROR_MESSAGE);
} finally {
try {
if (rs != null) rs.close();
} catch (SQLException ex) {
JOptionPane.showMessageDialog(obj_form,
ex.getMessage(),
"ERROR", JOptionPane.ERROR_MESSAGE);
}
}
}

public static void table_renderer(JTable jtable){


jtable.setDefaultRenderer(Object.class,
new TableCellRenderer(){
private DefaultTableCellRenderer
DEFAULT_RENDERER = new DefaultTableCellRenderer();
@Override
public Component
getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean
hasFocus, int row, int column) {
Component c =
DEFAULT_RENDERER.getTableCellRendererComponent(table,
value, isSelected, hasFocus, row, column);
if (row%2 == 0){
c.setBackground(Color.WHITE);
}
else {
c.setBackground(Color.LIGHT_GRAY);
}
return c;
}
});
}

//Sets columns header


public static String[] set_column_header(JTable
table, String header[]) {
for(int i=0;i<table.getColumnCount();i++)
{
TableColumn cols =
table.getTableHeader().getColumnModel().getColumn(i);
cols.setHeaderValue(header[i]);
}
return header;
}

//Finds selected item in combobox


public static <T> void
find_combo_value_selected(JComboBox<T> comboBox, T value)
{
boolean found = false;
for (int i = 0; i < comboBox.getItemCount(); i++)
{
T item = comboBox.getItemAt(i);
if (Objects.equals(item, value)) {
comboBox.setSelectedIndex(i);
found = true;
break;
}
}
if (!found) {
comboBox.setSelectedIndex(-1);
}
}

public static int item_to_display(JFrame frm, String


sql_min, String sql_max, JTextField jtf, String direction)
{
int currentValue = 1;

String text = jtf.getText();


if (text == null || text.trim().isEmpty()) {
return currentValue;
}
try {
currentValue = Integer.parseInt(text);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(frm,
ex.getMessage(), "ERROR", JOptionPane.ERROR_MESSAGE);
return currentValue;
}

switch (direction) {
case "first":
try (Connection conn = getConnection();
PreparedStatement ps =
conn.prepareStatement(sql_min)) {
ResultSet rs = ps.executeQuery();
if (rs.next()) {
currentValue = rs.getInt(1);
}
} catch (SQLException ex) {
JOptionPane.showMessageDialog(frm,
ex.getMessage(),
"ERROR", JOptionPane.ERROR_MESSAGE);
}catch(java.lang.NumberFormatException ex){
JOptionPane.showMessageDialog(frm, ex.getMessage(),
"ERROR",JOptionPane.ERROR_MESSAGE);
}
break;

case "prev":
try (Connection conn = getConnection();
PreparedStatement ps = conn.prepareStatement(sql_max))
{
ResultSet rs = ps.executeQuery();
if (rs.next()) {
int max = rs.getInt(1);
if (currentValue > 1) {
currentValue--;
} else {
currentValue = max;
}
}
} catch (SQLException ex) {
JOptionPane.showMessageDialog(frm, ex.getMessage(),
"ERROR", JOptionPane.ERROR_MESSAGE);
}catch(java.lang.NumberFormatException ex){
JOptionPane.showMessageDialog(frm, ex.getMessage(),
"ERROR",JOptionPane.ERROR_MESSAGE);
}
break;

case "next":
try (Connection conn = getConnection();
PreparedStatement ps = conn.prepareStatement(sql_max))
{
ResultSet rs = ps.executeQuery();
if (rs.next()) {
int max = rs.getInt(1);
if (currentValue < max) {
currentValue++;
} else {
currentValue = 1;
}
}
} catch (SQLException ex) {
JOptionPane.showMessageDialog(frm, ex.getMessage(),
"ERROR", JOptionPane.ERROR_MESSAGE);
}catch(java.lang.NumberFormatException ex){
JOptionPane.showMessageDialog(frm, ex.getMessage(),
"ERROR",JOptionPane.ERROR_MESSAGE);
}
break;

case "last":
try (Connection conn = getConnection();
PreparedStatement ps = conn.prepareStatement(sql_max))
{
ResultSet rs = ps.executeQuery();
if (rs.next()) {
currentValue = rs.getInt(1);
}
} catch (SQLException ex) {
JOptionPane.showMessageDialog(frm, ex.getMessage(),
"ERROR", JOptionPane.ERROR_MESSAGE);
}catch(java.lang.NumberFormatException ex){
JOptionPane.showMessageDialog(frm, ex.getMessage(),
"ERROR",JOptionPane.ERROR_MESSAGE);
}
break;
default:
break;
}
return currentValue;
}

/**
* Sets the Nimbus look and feel for a JFrame.
* @param frame the JFrame to set the look and feel for
*/
public static void setLookAndFeel(JFrame frame) {
try {
// Set the Nimbus look and feel
UIManager.setLookAndFeel(new NimbusLookAndFeel());

// Set the UI colors


UIManager.put("control", new Color(240, 240, 240));
UIManager.put("info", new Color(128, 128, 128));
UIManager.put("text", new Color(50, 50, 50));
UIManager.put("nimbusBase", new Color(50, 200, 20));
UIManager.put("nimbusAlertYellow", new Color(248, 187, 0));
UIManager.put("nimbusDisabledText", new Color(128, 128, 128));
UIManager.put("nimbusFocus", new Color(115, 164, 209));
UIManager.put("nimbusGreen", new Color(176, 179, 50));
UIManager.put("nimbusInfoBlue", new Color(66, 139, 221));
UIManager.put("nimbusLightBackground", new Color(220, 220,
220));
UIManager.put("nimbusOrange", new Color(191, 98, 4));
UIManager.put("nimbusRed", new Color(169, 46, 34));
UIManager.put("nimbusSelectedText", new Color(255, 255, 255));
UIManager.put("nimbusSelectionBackground", new Color(104, 93,
156));

// Update the UI for the JFrame


SwingUtilities.updateComponentTreeUI(frame);
} catch (UnsupportedLookAndFeelException e) {
System.err.println("Nimbus: Unsupported Look and feel!");
}
}

public static DefaultPieDataset


create_pie_dataset_from_categorized_vals(Map<String, Double> count_map) {
DefaultPieDataset dataset = new DefaultPieDataset();
count_map.forEach((key, value) -> dataset.setValue(key, value));
Another random document with
no related content on Scribd:
titrated hydrochloric acid. For general purposes, however, this
determination is usually of little interest.
398. Müller’s Modified Kjeldahl Method.—Numerous
difficulties, as stated by Müller,[263] have attended the attempts to
apply the kjeldahl method for the estimation of nitrogen to samples
of soil, and he has modified the method to some extent and made
comparisons of the quantity of nitrogen by this modified method and
by the soda-lime method.
The principal difficulty encountered by him has been in the regular
heating of the mixture of fuming sulfuric acid and soil. The particles
of soil are deposited at the bottom of the flask and the result is that
the bottom layers become overheated, and, being poor conductors of
heat, fail to transmit a sufficient quantity of heat to penetrate to the
upper layers of the liquid to complete the reaction. In order to avoid
this difficulty Müller heats his flask in a small stove formed with a
straight vertical cylinder of iron or copper, the upper end of which is
covered with a sheet of iron pierced with a hole which allows the
neck of the flask to pass through, while the lower end is closed with a
piece of sheet iron furnished on its upper surface with a layer of
asbestos. This cylinder of metal is surrounded with a second one,
concentric with the first through which passes a current of heated
gases furnished by an ordinary bunsen. By heating the flask in this
stove or furnace an even distribution of the heat is secured to all
parts of the mixture, but the little drops of sulfuric acid, which are
condensed on the cold part of the neck, sometimes lead to the
fracture of the glass as they run down the sides of the flask to the hot
portions. To prevent the reflux of this condensed acid, which only
needs to be done near the end of the reaction, when it is necessary to
heat to a very high temperature, the neck of the flask is bent at the
point immediately above its emergence at the upper surface of the
furnace, and carried into a flask of about seventy-five cubic
centimeters capacity, which will receive the drops of sulfuric acid
condensed during the operation. The furnace has the following
dimensions; height, twelve centimeters; diameter of interior
cylinder, five and one-half centimeters; diameter of exterior cylinder,
seven and one-half centimeters.
It is supported on a triangle of large iron wire and is heated by an
ordinary bunsen, or by a concentric bunsen, according to the
temperature which it is necessary to obtain. The proportions which
should be observed between the amount of earth employed and the
sulfuric acid are about as follows:
Of the dry earth, fifteen grams; of the fuming sulfuric acid, thirty
cubic centimeters. There should also be added to the mixture about
three-tenths of a gram of pure stearic acid, or better, benzoic acid.
When the soil to be analyzed does not contain carbonate, the sulfuric
acid should be added in two portions. At first add about twenty cubic
centimeters of the acid, and after shaking it, the other ten cubic
centimeters, running it in from a burette or a pipette in such a
manner as to wash thoroughly the neck and sides of the flask. If the
earth contain carbonate, however, it is necessary to add the fuming
acid in small portions of about five cubic centimeters at a time,
waiting each time until the disengagement of the gas caused by the
previous addition has ceased. A soil which contains from thirty to
forty per cent of calcium carbonate should be carefully treated in a
porcelain capsule with a slight excess of sulfuric acid, pure and
dilute. The mixture is afterward to be evaporated to dryness upon a
sand-bath and the residue heated in a drying oven to 110°. The mass
is then pulverized, introduced into the flask, treated with three-
tenths of a gram of benzoic acid and thirty cubic centimeters of
fuming sulfuric acid, and treated as indicated above. In all cases it is
necessary to continue the heating until the contents of the flask are
colorless.
With soils containing considerable quantities of iron, however, a
slight red color will probably be observed which will not interfere
with the accuracy of the tests.
The heating should at first be gentle and the temperature
afterward elevated little by little, and finally the heat should be
sufficiently great to distill about one and one-half cubic centimeters
of sulfuric acid. The operation lasts from twelve to thirteen hours. As
the reaction is terminated the cooled mass is taken up with water
absolutely free from ammonia. It is filtered into a flask, and washed
upon the filter until the volume of the filtered liquid is about 350
cubic centimeters. Afterward an excess of soda-lye, at 50° baumé is
added, then a few pieces of quartz to facilitate boiling. The flask is
then connected with a condenser, the liquid distilled and received in
a conical flask closed by a cork having two holes, of which one
permits the entrance of the end of the condenser, and the other a
glass tube which is connected with a small flask containing water, the
neck of the receiving flask being inclined toward the condenser to
avoid the entrainment of any of the alkaline liquid which may be
distilled. The receiving flask rests upon two or three pieces of sheet
iron and is heated with an ordinary burner, and ebullition is perfectly
regular. From 170 to 180 cubic centimeters of the liquid are distilled
in from three and one-half to four hours. The distilled liquid, treated
with a few drops of litmus, is titrated by a solution of sulfuric or
hydrochloric acid, of which one cubic centimeter corresponds to
0.001 cubic centimeter of nitrogen.
399. Modification of the Kjeldahl Method by Arnold and
Wedemeyer.[264]—For the oxidizing liquid a mixture of three grams
of benzoic acid with forty cubic centimeters of H₂SO₄ is employed.
After placing in the digestion flask with the nitrogenous body the
whole is gently shaken for a few minutes to prevent clotting. The
temperature is then raised until acid vapors begin to come off, when
one gram of copper sulfate and one gram of mercuric oxid are added;
and after ten to fifteen minutes, to avoid foaming, ten to twenty
grams of potassium sulfate. The sublimate noticed on the walls of the
flask is benzoic acid and does not interfere with the accuracy of the
determination.
This method has given good results with the alkaline nitrates, the
nitrates of barium, mercury, silver, lead, and with strychnia,
ammonia, pyridin, azobenzol, dinitrobenzol, and picric acid.
400. Prevention of Bumping During Distillation.—Daffert
has employed the modified kjeldahl method, but found considerable
difficulty in using the same owing to the violent bumping of the
liquid in the distillation. This was especially the case where the
sample contained a large proportion of sand. To overcome this
annoyance and danger he devised the following process:[265]
Fit into the mouth of a large-mouthed distillation flask a stopper
having two perforations. Through one of the perforations pass the
usual distillation tube, through the other a similar tube connected
with a supply of steam. Bring the contents to a brisk boil, after which
a small current of steam is turned on, allowing the same to pass in a
small stream throughout the distillation. By this means, not only is
all danger from bumping avoided, but the time required for the
distillation shortened. By the old method it usually requires from
fifteen to twenty minutes, whereas the former requires from six to
ten minutes.
It is advisable to filter all samples of soils having a large proportion
of sand.
401. Determination of Organic Nitrogen by the Soda-
Lime Method.—In the description of the method following, the
directions of the French Commission of Agricultural Chemists have
been taken as the basis of the analytical process.[266] This method is,
in this country, almost superseded by the moist combustion process
with sulfuric acid. By reason of its long use, however, and because it
is still regarded as the best method by the agricultural chemists of
France, Italy, and England, it merits a full description. It is
recommended also by Berthelot and André,[267] by the International
Congress of Chemists, held in Paris in 1889, by the Italian chemists,
and by the official Belgian method,[268] in all cases where nitrates are
not present in notable quantities.
The nitrogen which is found in soils in the organic state is
transformed into ammonia when it is heated with soda-lime. This
reaction is the base of the process of analysis which has so long been
used for this class of bodies. The analytical process is conducted as
follows:
A well-cleaned glass combustion tube, closed at one end, is used.
The length of the tube is from thirty-five to forty centimeters. It is
filled first to a depth of two centimeters with calcium oxalate;
afterwards to a depth of five centimeters with soda-lime in small
fragments; afterwards with the mixture to be analyzed; viz., of ten
grams of the sample of soil, or twenty grams if poor in nitrogen and
organic matters, with soda-lime reduced to a coarse powder. This
mixture should occupy a length of about twenty centimeters in the
tube. The soil and soda-lime are mixed in a mortar. Afterwards the
mortar is rubbed with small quantities of soda-lime, and this,
together with the copper boat which has been used in introducing the
mixture, is thoroughly washed with the soda-lime, which is poured
into the tube until it is filled to within four centimeters of its open
extremity. The open end of the tube is then closed with a wad of
asbestos packed sufficiently tight to prevent the carrying off of the
soda-lime by the gas which may be generated during the combustion.
The combustion should be commenced by heating the tube near the
open extremity until it is red and carrying the heat progressively
towards the part containing the soil mixed with the soda-lime. An
ordinary gas combustion furnace should be used and the heat
graduated in such a way that the bubbles of gas pass off regularly and
not too rapidly. The gas is conducted into a bulb tube containing a
decinormal standard sulfuric acid colored with litmus. The
combustion is continued until the whole of the organic material is
decomposed, care being taken not to raise the combustion tube
above a low redness in order to avoid its softening. At the end,
however, the temperature of the combustion tube should be raised to
a bright red, and the part containing the calcium oxalate should be
heated little by little for the purpose of evolving hydrogen, which is
used to drive out the last traces of ammonia. After the combustion is
completed, and the last traces of ammonia driven out, the standard
acid which has received the evolved ammonia is removed, the tube
leading to it washed, the wash-water collected with the rest of the
liquid and titrated with a standard solution of lime-water, the
strength of which has previously been determined against standard
sulfuric acid.
402. Preparation of the Standard Sulfuric Acid.—The
sulfuric acid to be used in making the standard solutions should be
previously boiled for half an hour in a platinum dish and allowed to
cool in a desiccator. It should contain 61.25 grams of sulfuric acid in
one liter. It is recommended that the flask which holds the sulfuric
acid should be one which has been used for a long time for holding
concentrated sulfuric acid, in order to avoid any action of the alkali
in the glass upon the acid after its strength has been determined. The
solution before described is of such strength as to have each cubic
centimeter equivalent to one milligram of nitrogen.
For the estimation of the nitrogen in the soil a tenth normal
solution should be used, which is prepared by taking 100 cubic
centimeters of the normal solution, described above, and diluting to
one liter.
Preparation of the Lime-Water.—From 200 to 300 grams of
slaked lime are placed in a closed flask of about five liters capacity.
This is filled with water and shaken frequently, and left to deposit the
matter in suspension. The water which contains the saline particles
which may have been present in the lime is then poured off. Fresh
water is then poured on and the flask shaken from time to time. To
use this lime-water the clear part of it is decanted into a flask,
avoiding, as much as possible, access to the air. The flask is closed
with a cork carrying two tubes drawn out and bent at a right angle.
One of these serves for pouring off the water and the other serves for
the entrance of the air. These two tubes are themselves closed by
means of a rubber tube carrying a pinch-cock. The strength of the
lime-water is fixed by titration with the decinormal standard sulfuric
acid.
Preparation of the Soda-Lime.—Six hundred grams of slaked lime
in fine powder are saturated with 300 grams of caustic soda
dissolved in 300 cubic centimeters of water. The whole is rubbed
into a paste and introduced into a crucible which is heated to
redness. The contents of the crucible, still hot, are poured out, and
rapidly reduced to fragments in a copper mortar in such a manner as
to have the pieces about the size of a pea, and without having too
much finely powdered soda-lime mixed with it. While the matter is
still hot it is placed in a flask and well-stoppered. In order that this
reagent should contain no nitrogen it is indispensable to use in its
preparation materials which contain no trace of nitrates.
Preparation of the Calcium Oxalate.—In a small copper vessel
place 100 grams of oxalic acid and add gradually, bringing it to
boiling, enough water to dissolve it. Afterwards place in the solution
small portions of slaked lime in a state of powder, constantly testing
it until turmeric paper indicates that there is a little lime in excess. It
is then evaporated, stirring vigorously on the open fire, and the
evaporation is finally finished on a steam-bath. The dried material is
placed in a flask and well-stoppered. The oxalic acid which is used in
this preparation should be free from every trace of nitrogen.
Preparation of the Litmus Solution.—Five grams of litmus are
placed in a flask with a flat bottom. Afterwards a few cubic
centimeters of ammonia are added, twenty five grams of crystallized
sodium carbonate, and ten cubic centimeters of water. This mixture
is left to digest for sometime, with frequent stirring, at a temperature
of from 60°–80°. The digestion is finished in about four or five days,
during which time, at intervals, a few drops of ammonia are added,
sufficient to maintain always the ammoniacal odor. At the end of this
time 200 cubic centimeters of water are added and the digestion
allowed to continue several days more, still maintaining the solution
alkaline with ammonia. A slight excess of hydrochloric acid is added,
and the matter which is precipitated is received upon a filter where it
is washed several times with cold water and allowed to dry at a low
temperature.
For use, from one to two grams of this dry precipitate are dissolved
in 100 cubic centimeters of alcohol, and there is thus obtained a
litmus solution of extreme sensibility.
403. Treatment of Soil Containing Nitrates.—Nitrates exist
in small quantities in all arable soils. When treated for nitrogen by
the soda-lime method above described, a part of the nitric nitrogen is
changed to the state of ammonia, while another part escapes
estimation altogether, causing an error which it is important to point
out. When the soils contain only small quantities of nitrates this
error is insignificant and does not affect sensibly the results, but in
the case of earths rich in nitrates it is necessary first to eliminate
them before the determination of the nitrogen by the soda-lime
method. The operation is carried on as follows:
Twenty grams of the soil are washed on a small funnel, furnished
with a plug of asbestos, with small quantities of pure water, in such a
way as to cause thirty to forty cubic centimeters of water to pass
through. The whole of the nitrate is thus removed. The soil is now
dried and submitted to analysis by the soda-lime method as just
described. There are removed with the nitrate only small traces of
organic nitrogen, too small to influence the results of the analysis. If,
however, it is desired to remove altogether this slight cause of error,
evaporate the wash-waters, above described, to two or three cubic
centimeters; add a few drops of a concentrated solution of ferrous
chlorid and as much hydrochloric acid, and boil some minutes in
order to drive off, in the state of nitrogen dioxid, all the nitric acid.
The residue is evaporated to dryness and contains the traces of
organic nitrogen. This is added to the soil which is to be treated by
the soda-lime method.
404. Müller’s Method.—The determination of nitrogen in the
soil by soda-lime is carried on as follows by Müller:[269]
Fifteen grams of fine earth, dried and mixed with a little sugar, are
mixed with thirty grams of soda-lime in powder. The bottom of the
combustion tube contains a little moist soda-lime, which is heated at
the end of the operation at the same time that a current of pure
hydrogen is made to pass through it, and the temperature of the tube
is raised, little by little, to a distinct redness. The contents of the
receiving bulbs are distilled, after the addition of water and soda, in
the same apparatus which served in the estimation of nitrogen, by
the kjeldahl method; the determinations and titrations are made also
under the same conditions.
Blank determinations are also made under the same conditions to
determine the amount of correction to be made by the two methods.
Soda-lime, heated with pure sugar, gave 0.0002 gram of nitrogen for
a total weight of fifty-five grams of the soda-lime contained in the
tube. The fuming sulfuric acid gave 0.0011 cubic centimeters of
ammoniacal nitrogen for the volume of thirty cubic centimeters.
The numbers obtained by the kjeldahl method in general, are
lower than those obtained by the soda-lime method when no stearic
or benzoic acid is used. The numbers obtained when stearic acid
alone was used were sometimes inferior to those obtained by the
soda-lime method. The numbers obtained when benzoic acid is used
are, in general, about the same as those obtained by the soda-lime
method.
It would seem that the double distillation, outlined above, for the
kjeldahl method, would not be necessary if due care were exercised
in the first distillation. This variation, therefore, seems to be
unnecessary.
In the soda-lime method, time would be saved by the reception of
the ammonia in standard acid, and its titration in the usual way,
unless a further purification of the nitrogenous products of the
combustion by the final distillation be desired.
405. Volumetric Determination of the Nitrogen.—Instead
of separating the nitrates, the total nitrogen in the soil can be
determined directly by the classic method of Dumas, which consists
in bringing the whole of the nitrogen into a gaseous state and
afterwards measuring its volume.
The following method illustrates the general principles of the
determination:
A glass combustion tube closed at one end, about one meter in
length, is selected. In the bottom of this tube is placed some
potassium bicarbonate in a crystalline form, in small pieces, filling
the tube to a distance of about twenty centimeters. Afterwards
copper oxid is placed to the depth of ten centimeters and finally a
mixture of from twenty to thirty grams of the earth with thirty to
forty grams of copper oxid in a fine state of subdivision, and about
ten grams of metallic copper obtained by reducing the copper oxid by
hydrogen. Next the tube is filled with copper oxid to a depth of from
twenty to twenty-five centimeters, and afterwards with reduced
copper to the depth of at least twenty-five centimeters, and after this
another layer of copper oxid of about five centimeters, and finally a
plug of asbestos. The combustion tube is closed with a stopper
carrying a glass tube of about ninety centimeters in length, of which
the extremity, bent into the form of a ᥩ, extends to a mercury
trough. The glass combustion tube is surrounded with brass gauze,
except that part which contains the potassium bicarbonate. The
beginning of the operation consists in heating the tube to decompose
a part of the potassium bicarbonate, until the whole of the apparatus
is filled with carbon dioxid. In order to determine that the whole of
the air has been expelled and that the apparatus is entirely filled with
carbon dioxid, a part of the gas which is disengaged, is received into
a jar filled with mercury, in which a little potash-lye has been placed.
If the gas is entirely absorbed by the potash, so that there remain
only unappreciable particles, the tube can be regarded as completely
free of air. When assurance is given that the air is all out of the
apparatus, a jar of about 300 cubic centimeters capacity, filled with
mercury and containing from thirty to forty cubic centimeters of a
solution of potash of a density of 42° baumé, is placed over the outlet
tube. The combustion is commenced by heating the anterior part of
the tube, avoiding the heating of the part containing the earth. When
the first part of the tube has reached the red stage the part containing
the earth is gradually heated in order to obtain a gentle evolution of
gas. The temperature of the tube is carried to redness and the
heating gradually carried back toward the closed extremity, but
avoiding raising the temperature of the part containing the
potassium bicarbonate. The red heat is continued as long as bubbles
of gas are discharged into the reservoir. When the evolution of gas
has ceased the apparatus is again filled with carbon dioxid for the
purpose of driving out the last traces of nitrogen, by heating again
the part of the tube containing the potassium bicarbonate. The
evolution of the carbon dioxid should be maintained for about fifteen
minutes. At the end of this time all the nitrogen will be found in the
receiving jar. Sometimes a small quantity of nitrogen dioxid is
formed incidentally in the operation. After waiting for a quarter of an
hour, in order to permit all the carbon dioxid which may have
escaped into the reservoir to be completely absorbed, the receiving
jar is carried to a water-basin and the mercury allowed gradually to
escape; its place being taken by the water. The gas is then transferred
into an azotometer where its volume and temperature are read in the
usual way.
In order to absorb any nitrogen dioxid which may be admixed with
the nitrogen itself, a little crystal of ferrous sulfate is introduced. The
reservoir containing the nitrogen is carried to the mercury trough,
and the water which it contains is nearly all run out in such a way as
to be replaced with mercury, great care being exercised to avoid any
escape of gas. Afterwards there is introduced over the mercury a
crystal of ferrous sulfate and the azotometer is shaken until this
crystal is dissolved by the water which it still contains. It is then
allowed to remain for twenty hours. At the end of this time the
nitrogen dioxid is absorbed and the volume of the gas is again read
as before. One-half only of the total loss should be subtracted, since
the volume of the nitrogen dioxid is twice the volume of the nitrogen
itself. For the practice of this method, in connection with the use of a
mercury pump, the directions which will be given under fertilizers
may be consulted.
406. Estimation of Ammonia.—Ammonia exists ordinarily
only in very small quantities in the soil, since it is incessantly
transformed into nitrate or diffused in the air. Nevertheless, it is
sometimes interesting to determine its quantity.
The method of determining the ammonia in soils is one of extreme
delicacy on account of the small proportion therein, and the difficulty
of expelling it without at the same time converting some of the
organic nitrogen into ammoniacal compounds. The various methods
employed for this purpose may be classified as follows:
1. Treatment of the soil with soda-lye in the cold, and the
absorption of the ammonia given off by standard sulfuric acid.
2. The method of Boussingault, which consists in replacing the
soda-lye with magnesia and distilling the ammonia at a boiling
temperature, absorbing the distillate in a standard acid.
3. A modification of the above method, due to Schloesing, which
consists first in extracting the ammonia by hydrochloric acid and
subjecting the extract to distillation with magnesia.
4. The method of Knop consists in treating the soil in a closed
cylinder with soda-lye containing bromin. The ammonia set free by
the lye is decomposed in the presence of bromin into free nitrogen
and hydrochloric acid. The nitrogen is collected and measured in an
azotometer. The brom-soda-lye is prepared by dissolving 100 grams
of sodium hydroxid in 1,200 cubic centimeters of water and adding
twenty-five cubic centimeters of bromin.
5. The process described under 4, as shown by Baumann,[270] does
not give accurate results and it has been modified by him as follows:
Two hundred grams of soil are treated with 100 cubic centimeters of
dilute hydrochloric acid (one part acid and four of water) free of
ammonia; 300 cubic centimeters of ammonia-free distilled water are
added and the whole digested for two hours with frequent stirring. If
a soil contain much calcium carbonate larger quantities of acid must
be used. Two hundred cubic centimeters of the filtrate are placed in
an evolution flask, connected with an azotometer, with five grams of
freshly burned magnesia. The mixture is then oxidized as follows:
Ozone is generated by adding three parts by weight of sulfuric acid to
one part of dry and powdered potassium permanganate. A stream of
air is drawn through the ozone generator by an aspirator, and the
ozone is conducted into a flask containing the hydrochloric acid
extract of the soil and magnesia. The oxidation is completed in about
ten minutes. The mixture is then brought into the evolution flask of
the azotometer and the nitrogen set free and measured in the usual
way.
It has been shown that if asparagin or glutamin be present in the
soil they are decomposed by the soda-lye and the results obtained are
too high. It has been further proved that soils which contain a
notable quantity of humus give, with soda-lye in the cold, a
practically continuous evolution of ammonia. Moreover, soils which
are rich in humus and which have been treated by distillation with
magnesia give, on subsequent treatment with soda-lye, considerable
additional quantities of ammonia.
Comparison of Methods of Estimating Ammonia.—Baumann has
determined the ammonia-nitrogen in various soils by the soda-lime
method; distillation of the hydrochloric acid extract with magnesia,
and the azotometric method modified as indicated above. These
methods will be designated as 1, 2, 3, respectively in the following
table.

Method.
1. 2. 3.
Ammonia-nitrogen in one kilogram of soil.

No. of sample. Gram. Gram. Gram.


1 0.0448 0.02227 0.02781
2 0.0168 0.01105 0.01326
3 0.0336 0.01771 0.02214
4 0.0056 0.00443 0.00443
5 0.0280 0.02337 0.02894
6 0.0196 0.01243 0.01672

From the above figures it is seen that the method usually


attributed to Schloesing gives uniformly higher numbers than either
of the other processes, while the third gives slightly higher values
than the second.
407. The Magnesia Distillation Process.—If a sample of soil
be distilled directly with magnesia and water, there is danger on the
one side of not extracting all the ammonia, by reason of the
absorbing power of these bodies, and on the other, of transforming
into ammonia the nitrogen of the organic matters. It is therefore
preferable to separate the ammonia from the soil in the form of
chlorid, and to subject this extract to distillation.
In fifty grams of the soil the humidity is determined by drying at
100° until there is no further loss of weight. The quantity of moisture
being known, 200 grams of soil are taken and moistened with water,
and then there is added, in small portions, some dilute hydrochloric
acid, shaking frequently until the whole of the calcium carbonate
present is decomposed. The liquor should remain acid at the end of
the operation, but without containing a notable excess of acidity.
Knowing beforehand the quantity of moisture contained in the 200
grams, water is added until the total quantity shall be equal to 500
cubic centimeters. The whole is then shaken and allowed to repose,
and filtered rapidly, covering the funnel with a glass vessel and
receiving the liquid which runs through in a flask with a narrow
opening. Two hundred and fifty cubic centimeters of this liquor, or
mixture, represent 100 grams of earth of known humidity. This
quantity is introduced into a flask for determining the ammonia and
five grams of calcined magnesia added. Before commencing the
distillation, assurance should be had that the magnesia has
completely saturated the acid in excess, and that the liquor is
alkaline.
If, by chance, the liquor should be still acid it would be necessary
to add sufficient magnesia in order that the reaction should be
manifestly alkaline. Afterwards the distillation is begun and the
ammonia is received in an appropriate vessel containing one-tenth
normal sulfuric acid and titrated in the usual way, or nesslerized.
Inasmuch as the quantities of ammonia contained in the earth are
generally very small it is necessary to be very particular in order to
avoid errors. The distilled water which is employed should be
deprived of all traces of ammonia by prolonged ebullition, and the
hydrochloric acid should be distilled in the presence of a little
sulfuric acid. The treatment with hydrochloric acid is for the purpose
of destroying the absorbing properties of the soil for ammonia, and
to permit this last to enter into solution as chlorid. When there is
need of very great precision it is convenient to make a blank
operation with the hydrochloric acid and water which are employed,
in order to make a correction for the traces of ammonia which these
reagents may contain.
408. Estimation of Ammoniacal and Amid Nitrogen by
the Method of Berthelot and André.[271]—Heat one hundred
grams of earth for thirty hours on a steam-bath with about .500
cubic centimeters of dilute hydrochloric acid (fifteen grams of
hydrochloric acid to 500 cubic centimeters of water). At the end of
this time throw the contents of the flask on a filter and wash with hot
water until acid reaction has ceased. Determine both the ammoniacal
and amid nitrogen in the soluble, and the total nitrogen in the
insoluble portion, the ammoniacal by distillation with magnesia, and
the amid and total with soda-lime.
Example. A soil contained 0.1669 per cent total nitrogen. Of this
there were obtained:

As ammoniacal nitrogen 13.7 per cent


In the soluble part as amid nitrogen 56.2 „ „
In the insoluble part, total nitrogen 29.7 „ „

Sum 99.6 „ „

Treatment of the Insoluble Portion.—Treat the part insoluble in


hydrochloric acid with a three per cent solution of potash on a steam-
bath for thirty hours. Estimate the nitrogen remaining insoluble,
from which the part dissolved can be determined by difference. The
potash will dissolve usually about two-thirds of the remaining
nitrogen.
About ninety per cent of the total nitrogen present in an arable soil
will be rendered soluble by successive treatment with acid and alkali.
The reverse treatment will give practically the same result. It is
therefore immaterial, from an analytical standpoint, whether the
acid or alkali be used first.
409. Estimation of Volatile Nitrogenous Compounds
Emitted by Arable Soil.—The following method, due to Berthelot
and André,[272] may be practiced:
Porcelain pots, containing one kilogram of soil, are placed under
bell-jars of fifty liters capacity adjusted to glass dishes designed to
receive the waters of condensation.
During the first period the pots are to be sprinkled from time to
time, during the duration of the experiment, through the upper
tubulature, so as to prevent the soil from becoming dry. The water is
partly condensed on the sides of the bell-jar. It is removed each week
through the inferior tubulature, treated with a little dilute sulfuric
acid, and preserved for further study. A small vessel containing
dilute sulfuric acid is placed near the porcelain pot for the purpose of
collecting, as far as possible, the evolved ammonia.
During the second period the pots are not sprinkled, the soil
becomes dry and there is no longer any condensation of water on the
walls of the bell-jar. The two periods should include about five
months, from May to October.
At the end of the second period the following determinations are to
be made:
1. The ammonia absorbed by the dilute sulfuric acid.
2. The ammonia set free by distillation with magnesia, such as may
have accumulated in the condensed water.
3. The organic nitrogen contained in the latter after elimination of
the ammonia. This is determined by adding a slight excess of acid,
evaporation to dryness, and combustion with soda-lime, or by moist
combustion with sulfuric acid.
Example:
Earth Employed.—One kilogram of sandy clay containing total
nitrogen, 0.09 gram. Nitrogen in sprinkling water, 0.000048 gram.
Nitrogen in Exhaled Products.—

First Period. Sprinkling.


Ammoniacal nitrogen collected in the dilute sulfuric acid 0.00012 gram.
Ammoniacal nitrogen collected in the condensation waters 0.00012 „
Organic nitrogen in condensation waters 0.00220 „

Sum 0.00244 „

Second Period. No Sprinkling.


Ammoniacal nitrogen in dilute sulfuric acid 0.000007 gram.
„ „ „ condensed water 0.000007 „
Organic „ „ „ „ 0.000040 „

Sum 0.000054 „

Conclusions.—The exhalation of nitrogenous compounds takes


place with a certain relative activity, about two milligrams in two
months and a half, as long as the soil is kept moist by sprinkling.
In the second period, without sprinkling, the exhalation is reduced
to a mere trace.
The vessel containing the dilute sulfuric acid placed near the
porcelain pot absorbs only about one-half of the ammoniacal
nitrogen set free. The nitrogen emitted under other forms than
ammonia is, in every instance, greatly superior in quantity, and this
is the most important of the observed phenomena. This is true at
least with the kind of soil with which the experiment was made. With
arable soil containing twenty times as much nitrogen as the soil
described above this order is reversed,[273] the ammoniacal prevailing
over the non-ammoniacal nitrogen volatilized.
These phenomena are doubtless greatly influenced in soil under
culture by microbes, and the lowest orders of vegetation to which are
doubtless due the traces of non-ammoniacal volatile nitrogenous
compounds, a sort of vegetable ptomaines.
410. General Conclusions.—In the light of our present
knowledge concerning the methods of nitrogen determination in the
soil in the form of organic compounds and ammonia, moist
combustion with sulfuric acid is to be preferred to the older soda-
lime process. For the nitrogen combined as ammonia, the extraction
of the sample with hydrochloric acid and subsequent distillation with
an excess of freshly calcined magnesia, are recommended. For the
study of the progressive decomposition of the nitrogenous
compounds, the various processes devised by Berthelot and André
are the best.
The origin of the nitric acid in the soil, the methods of studying the
various nitrifying organisms, and of estimating the nitric acid
produced, will form the subject of the next part.
Note.—At the Eleventh Annual Convention of the Association of
Official Agricultural Chemists, held in Washington, August 23, 24
and 25, 1894, the following process of soil extraction was adopted as
the official method:
Preparation of the Sample.—500 grams or more, of the air-dried
soil, which may be either the original soil or that which has been
passed through a sieve of coarser mesh, are sifted upon a sieve with
circular openings one-half millimeter in diameter, rubbing, if
necessary, with a rubber pestle in a mortar, until the fine earth has
been separated as completely as possible from the particles that are
too coarse to pass through the sieve. The fine earths thoroughly
mixed and preserved in a tightly stoppered bottle from which the
portions for analysis are weighed out.
The coarse part is weighed and may be subjected to further
examination, (as in Bulletin 38, Div. of Chem., pp. 65, 75 and 200.) It
may sometimes be necessary to wash the soil through the one-half
millimeter sieve with water, in which case proceed as directed on pp.
65 and 75 of the above Bulletin. The use of water is to be avoided
whenever possible.
Determination of Moisture.—Heat two to five grams of the air-
dried soil in a flat-bottomed, tared platinum dish; heat for five hours
in a water-oven kept briskly boiling; cover the dish, cool in a
desiccator, and weigh.
Repeat the heating, cooling, and weighing at intervals of two hours
till constant weight is found, and estimate the moisture by the loss of
weight. Weigh rapidly to avoid absorption of moisture from the air.
An air-bath must not be used in this determination.
Determination of Volatile Matter.—The platinum dish and soil
used to determine moisture are used also to determine volatile
matter. Heat the dish and dried soil to full redness until all organic
matter is burned away. If the soil contain appreciable quantities of
carbonates, the contents of the dish, after cooling, are to be
moistened with a few drops of a saturated solution of ammonium
carbonate, dried and heated to dull redness to expel ammonium
salts, cooled in the desiccator and weighed.
The loss in weight represents the organic matter, water of
combination, ammonium salts, etc.
Extraction of Acid-Soluble Materials.—In the following scheme for
soil analysis it is intended to use the air-dried soil from the sample
bottle for each separate investigation. The determination of
moisture, made once for all on a separate portion of air-dried soil,
will afford the datum for calculating the results of analysis upon the
soil dried at the temperature of boiling water. It is not desirable to
ignite the soil before analysis or to heat it so as to change its chemical
properties.
The acid digestion is to be performed in a flask so arranged that
the evaporation of acid shall be reduced to a minimum, but to take
place under atmospheric pressure and at the temperature of boiling
water. Any flask resistant to acids is suitable, but it is not necessary
to use a condenser, as a simple bohemian glass tube eighteen inches
in length will answer the purpose of preventing loss of acid. Where it
is not desired to determine sulfur trioxid, an erlenmeyer fitted with a
rubber stopper and hard glass tube will answer. The flask must be
immersed in the water-bath up to the neck or at least to the level of
the acid and the water must be kept boiling continuously during the
digestion.
In the following scheme, ten grams of soil are taken, this being a
convenient quantity in most soils, in which the insoluble matter is
about eighty per cent. If desired, a larger quantity of such soil may be
taken, using a proportionately larger quantity of acid and making up
the soil solution to a proportionately larger volume. In very sandy
soils, where the proportion of insoluble matter is ninety per cent or
more, twenty grams of soil are to be digested with 100 cubic
centimeters of acid and the solution made up to 500 cubic
centimeters or a larger quantity may be used, preserving the same
proportions. It is very important that the analyst assure himself of
the purity of all the reagents to be used in the analysis of soils before
beginning the work.
Acid Digestion of the Soil.—Place ten grams of the air-dried soil in
a 150 to 200 cubic centimeter bohemian flask, add 100 cubic
centimeters of pure hydrochloric acid of specific gravity 1.115, insert
the stopper with condensing tube, place in a water or steam-bath and
digest for ten hours continuously at the temperature of boiling water,
shaking once each hour. Pour the clear liquid from the flask into a
small beaker, wash the residue out of the flask with distilled water on
a filter adding the washings to the contents of the beaker. The
residue after washing until free of acid, is to be dried and ignited as
directed below. Add one or two cubic centimeters of nitric acid to the
filtrate, and evaporate to dryness on the water-bath, finishing on a
sand or air-bath to complete dryness; take up with hot water and a
few cubic centimeters of hydrochloric acid, and again evaporate to
complete dryness. Take up as before, filter and wash thoroughly with
cold water or with hot water slightly acidified at first with
hydrochloric acid. Cool and make up to 500 cubic centimeters. This
is solution “A.” The residue is to be added to the main residue and
the whole ignited and weighed, giving the insoluble matter.
The determination of the various components of the solution
remains essentially as described in the provisional methods of the
Association which have already been given.
It is directed that all results of soil analysis be calculated on the
basis of the sample dried to constant weight at the temperature of
boiling water.
AUTHORITIES CITED IN PART SIXTH.

You might also like