Электронный магазин на Java и XML

       

Класс Order


Класс Order служит в основном в качестве контейнера для всевозможных сведений, которые мы собираем при оформлении заказа. Сюда входит информация о клиенте, о доставке, номер кредитной карты клиента, перечень заказанных товаров и данные, присланные поставщиком услуг по обработке (в частности, код подтверждения). Нам также понадобится уникальный идентификатор этого заказа, чтобы на него можно было впоследствии ссылаться. Кроме того, нужно указать дату заказа. Все эти сведения вносятся в соответствующие поля класса Order. Конструктор класса задает идентификатор и дату заказа. Метод, используемый для генерации уникального идентификатора, мы исследуем несколько позже. В листинге 5.5 показаны методы getXxx и setXxx для полей класса. Для полей id и date методы setXxx отсутствуют, так как их значения задаются конструктором класса и затем не меняются.

Листинг 5.5. Поля, конструктор и методы setXxx и getXxx для класса Order (Order.java)

package com.XmlEcomBook.Chap05;

import com.XmlEcomBook.catalog.CartItem;

import java.util.*;

import java.io.*;

import com.XmlEcomBook.util.Debug;

public class Order {

private int id; //unique id for this order

private Date date; //date of order

private Vector items = new Vector();

private CustomerInfo customerInfo;



private Authorization authorization; //payment authorization

private Fulfillment fulfillment;

public Order() {

id = getUniqueId();

date = new Date();

}

public int getId() {

return id;

}

public Date getDate() {

return date;

}

public void setItems( Vector newItems ) {

if( newItems != null )

items = newItems;

}

public Vector getItems() {

return items;

}

public void setCustomerInfo( CustomerInfo newCustomer ) {

if( newCustomer != null )

customerInfo = newCustomer;

}

public CustomerInfo getCustomerInfo() {

return customerInfo;

}

public void setAuthorization( Authorization newAuth ) {

authorization = newAuth;

}

public Authorization getAuthorization() {

return authorization;

}

public void setFulfillment( Fulfillment newFulfillment ) {


fulfillment = newFulfillment;

}

public Fulfillment getFulfillment() {

return fulfillment;

}

В листинге 5. 6 показаны некоторые методы, оперирующие данными, которые содержатся в классе Order. Первый метод, getTotalltemPrice, реализует цикл по всем заказанным товарам и для каждого товара умножает его цену на количество заказанных экземпляров. Затем подсчитывается и возвращается общая сумма. Метод getOrderTotal добавляет к общей сумме стоимость доставки, что и составляет общую стоимость заказа. Наконец, имеется метод getTotalltemWeight, который аналогичен методу getTotalltemPrice, но только в нем подсчитывается не стоимость, а общий вес заказа. Метод getPrice-осуществляет вспомогательные функции — удаляет дополнительные символы (знак $ и запятые) из строки с указанием цены, полученной из объекта Cartltem, а затем преобразует полученное число к типу doubl e.



Листинг 5.6. Методы для подсчета характеристик заказа как единого целого (Order.java)

public double getTotalItemPrice() {

double total = 0;

Enumeration enum = items.elements();

while( enum.hasMoreElements() ) {

CartItem item = (CartItem)enum.nextElement();

total += getPrice( item ) * item.getNumberOrdered();

}

return total;

}

public double getTotalItemWeight() {

double total = 0;

Enumeration enum = items.elements();

while( enum.hasMoreElements() ) {

CartItem cartItem = (CartItem)enum.nextElement();

double d = Double.parseDouble(cartItem.getShippingValue());

total += d * cartItem.getNumberOrdered();

}

return total;

}

private double getPrice( CartItem item ) {

String s = item.getPrice();

//remove dollar sign

s = s.replace( '$', ' ' );

//remove commas

int i;

while( (i = s.indexOf( ',' )) > 0 ) {

s = s.substring( 0, i ) + s.substring( i + 1 );

}

return Double.parseDouble( s );

}

Имеется также метод для записи заказа в формате XML. Информация о заказе может пригодиться в будущем. Поэтому мы создали определение DTD, которое является непосредственным отображением класса Order и всех классов, которые в нем используются. В листинге 5.7 представлен файл order.dtd, в котором каждому из полей класса Order (item, customer-Info, authorization и fullfilment) соответствует элемент, дочерний по отношению к элементу order. Поля id и date класса Order представлены атрибутами элемента order. Таким же образом сформированы и остальные элементы DTD: каждому полю класса Order соответствует элемент или атрибут в DTD [Order — заказ, item — товар, first name — имя, last name — фамилия, address — адрес, city — город, state — штат или страна, zip — почтовый индекс, phone — номер телефона, card number — номер кредитной карты, card type — тип кредитной карты, expiration date — дата окончания срока действия, reason — причина (отклонения кредитной карты), authorization code — код подтверждения, cost — стоимость, tracking number — номер для отслеживания заказа, date sent — дата отправки. — Примеч. перев. ].





Листинг 5.7. DTD для описания структуры заказа (order.dtd)

<!ELEMENT order (item*, customer_info, authorization, fulfillment )>

<!ATTLIST order id ID #REQUIRED

date CDATA #REQUIRED>

<!ELEMENT item (#PCDATA)>

<!ATTLIST item id NMTOKEN #REQUIRED

quantity NMTOKEN #REQUIRED

price CDATA #REQUIRED>

<!ELEMENT customer_info (first_name, last_name, address1, address2,

city, state, zip, email, phone, credit_info )>

<!ELEMENT first_name (#PCDATA)>

<!ELEMENT last_name (#PCDATA)>

<!ELEMENT address1 (#PCDATA)>

<!ELEMENT address2 (#PCDATA)>

<!ELEMENT city (#PCDATA)>

<!ELEMENT state (#PCDATA)>

<!ELEMENT zip (#PCDATA)>

<!ELEMENT email (#PCDATA)>

<!ELEMENT phone (#PCDATA)>

<!ELEMENT credit_info (card_numer, card_type, expiration )>

<!ELEMENT card_number (#PCDATA)>

<!ELEMENT card_type (#PCDATA)>

<!ELEMENT expiration_date (#PCDATA)>

<!ELEMENT authorization (reason?, auth_code?)>

<!ATTLIST authorization approved CDATA #IMPLIED>

<!ELEMENT reason (#PCDATA)>

<!ELEMENT authorization_code (#PCDATA)>

<!ELEMENT fulfillment (backorder_date, shipper, shipping_class,

cost, tracking_number, date_sent)>

<!ELEMENT shipper (#PCDATA)>

<!ELEMENT shipping_class (#PCDATA)>

<!ELEMENT cost (#PCDATA)>

<!ELEMENT tracking_number (#PCDATA)>

<!ELEMENT date_sent (#PCDATA)>

В листинге 5.8 приведен метод, который создает документ XML, соответствующий этому определению DTD. Это примитивный, слишком прямолинейный метод, в котором просто перебираются все поля класса Order и для каждого поля выписываются элементы и атрибуты XML. Такой подход не всегда является оптимальным, так как изменения в классах, входящих в класс Order, приведут к необходимости изменения самого метода. Таким образом, теряются преимущества инкапсуляции, которую обеспечивает объектно-ориентированный подход к программированию. Было бы лучше рассматривать эти классы в единстве. Более удачный метод создания документа XML мы рассмотрим в главе 6.





Листинг 5.8. Метод writeXML (Order.java)

public void writeXML( Writer writer ) {

try {

writer.write( "<?xml version='1.0' ?>" );

writer.write( "<!DOCTYPE order SYSTEM '.."

+ File.separator + "order.dtd'>" );

writer.write( "<order id='" + id + "' " );

writer.write( "date='" + date + "'>" );

Enumeration enum = items.elements();

while( enum.hasMoreElements() ) {

CartItem item = (CartItem)enum.nextElement();

writer.write( "<item id='" + item.getId() + "' " );

writer.write( "quantity='" + item.getNumberOrdered() + "' ");

writer.write( "price='" + item.getPrice() + "'>" );

writer.write( item.getName() + "</item>" );

}

writer.write( "<customer_info>\n<first_name>" +

customerInfo.getFirstName() + "</first_name>" +

"\n<last_name>" + customerInfo.getLastName() + "</last_name>" +

"\n<address1>" + customerInfo.getAddress1() + "</address1>" +

"\n<address2>" + customerInfo.getAddress2() + "</address2>" +

"\n<city>" + customerInfo.getCity() + "</city>" +

"\n<state>" + customerInfo.getState() + "</state>" +

"\n<zip>" + customerInfo.getZip() + "</zip>" +

"\n<email>" + customerInfo.getEmail() + "</email>" +

"\n<phone>" + customerInfo.getPhoneNumber() + "</phone>" );

CreditInfo credit = customerInfo.getCreditInfo();

writer.write( "\n<credit_info>\n<card_number>" +

credit.getCreditCardNumber() + "</card_number>" +

"\n<card_type>" + credit.getCreditCardType() + "</card_type>" +

"\n<expiration_date>" + credit.getExpirationDate() +



"</expiration_date>\n</credit_info>\n</customer_info>" );

writer.write( "\n<authorization approved='" +

authorization.isApproved() + "'>" +"\n<reason>" +

authorization.getReason() + "</reason>\n<authorization_code>" +

authorization.getAuthorizationCode() + "</authorization_code>" +

"</authorization>" );

writer.write( "\n<fulfillment>\n" +

"\n<shipper>" + fulfillment.getShipper() + "</shipper>" +

"\n<class>" + fulfillment.getShippingClass() + "</class>" +

"\n<cost>" + fulfillment.getCostToCustomer() + "</cost>" +

"\n<tracking_number>" + fulfillment.getTrackingNumber() +

"</tracking_number>\n<date_sent>" +

fulfillment.getDateSent() + "</date_sent>\n</fulfillment>" );

writer.write( "\n</order>" );

}

catch( IOException e ) {

}

}

Последний метод в классе Order, названный getllniqueld, приведен в листинге 5.9. Он генерирует уникальный идентификатор заказа. В нашем случае мы используем счетчик, который увеличивается на единицу каждый раз, когда нам требуется новый идентификатор. Этот счетчик должен храниться постоянно, чтобы мы могли быть уверенны в уникальности присваиваемых идентификаторов даже после полной перезагрузки системы. Хранение счетчика в памяти — в данном случае не выход из положения, так как при каждой перезагрузке системы счетчик начинает повторять уже присвоенные ранее идентификаторы. В качестве постоянного места хранения счетчика мы используем специальный файл.



Листинг 5.9. Метод getUniqueld (Order.java)

synchronized private int getUniqueId() {

int id;

try {

ObjectInputStream in = new ObjectInputStream( new

FileInputStream( "orderID.txt" ) );

id = in.readInt();

}

catch( IOException e ) {

id = 1000;

}

try {

ObjectOutputStream out = new ObjectOutputStream( new

FileOutputStream( "orderID.txt" ) );

out.writeInt( id + 1 );

out.close();

}

catch( IOException e ) {

}

return id;

}

}

 




Содержание раздела