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

       

Класс Catalog


Класс Catalog представляет корневой элемент DTD каталога, приведенного ниже: <!ELEMENT catalog (product_line*)>

У этого элемента нет атрибутов и имеется только один многократно повторяемый дочерний элемент с именем productjline. В листинге 6.1 приведена первая часть кода для объявления класса Catalog.

Листинг 6.1. Первая часть кода для объявления класса Catalog (Catalog.java)

package com.XmlEcomBook.Chap06;

import javax.xml.parsers.*;

import java.util.*;

import java.io.*;

import org.w3c.dom.*;

import org.xml.sax.*;

public class Catalog {

private Vector productLines = new Vector();

В этом коде формат имен, принятый в XML (нижний регистр с символом подчеркивания в качестве разделителя, например quantity_in_stock), был изменен на формат, соответствующий стандартному синтаксису Java. Имена классов начинаются с прописной буквы, и для разделения различных слов, составляющих одно имя, используются также прописные буквы, а не символы подчеркивания. Элемент с именем catalog становится классом Catalog.

Так как у элемента catalog может быть любое количество дочерних элементов product_l i ne, для их представления используется вектор Vector. Вообще, для представления повторяющихся элементов пригодна любая коллекция. Выбор конкретного вида коллекции основан на ее предполагаемом назначении; Vector является хорошим вариантом коллекции для тех случаев, когда вы не знаете заранее всех подробностей того, как будет использоваться коллекция.



Поскольку задачей данного класса является преобразование данных из XML к объектам Java и затем снова к XML, создается конструктор, которому в качестве параметра передается имя файла XML и который анализирует этот файл для извлечения из него данных. Конструктор показан в листинге 6.2.

Первая часть кода конструктора создает необходимые для анализа файла XML объекты JAXP. Также создается объект DocumentBuilder, который используется для анализа документа и получения объекта DOM Document.

В следующей части кода извлекается корневой элемент документа и все элементы типа product_l i ne. Выполняется цикл по этим элементам, и для каждого создается новый объект ProductLine; затем вызывается метод, который добавляет этот объект к объекту Catalog. Как вы видите, в классе Catalog требуется только найти прямые потомки объекта Catalog и передать их для дальнейшей обработки классу ProductLine.




Листинг 6.2. Конструктор класса Catalog (Catalog.java)

public Catalog( String filename) throws IOException { Document document = null; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { DocumentBuilder builder = factory.newDocumentBuilder(); document = builder.parse( new File( filename ) ); } catch( ParserConfigurationException pce ) { throw new IOException( "Parser Configuration Error" ); } catch( SAXException se ) { throw new IOException( "Parsing Excpetion" ); }

Element root = document.getDocumentElement(); NodeList nodes = root.getElementsByTagName ( "product_line" ); int num = nodes.getLength(); for( int i = 0; i < num; i++ ) { Element e = (Element)nodes.item( i ); ProductLine pl = new ProductLine( e ); addProductLine( pl ); } }

Устройство метода addProductLi ne, представленного в листинге 6.3, достаточно очевидно. Ему передается объект ProductLine, который затем добавляется в вектор productLines.



Листинг 6.З. Добавление новых серий товаров — элементов ProductLine (Catalog .Java)

public void addProductLine( ProductLine productLine ) { productLines.addEleraent( productLine ); }

Далее, вам нужен метод для доступа к объектам ProductLine, которые содержатся в объекте Catalog. Так как серии товаров идентифицируются по своим названиям, нужен метод, который извлекал бы объект на основании его имени. Этот метод показан в листинге 6.4. Методу getProductLine передается в качестве параметра название серии товаров, а затем в этом методе выполняется цикл по всем сериям товаров в каталоге, пока не будет найдена серия с этим именем. Если ни одна серия не найдена, возвращается nul 1.



Листинг 6.4. Поиск объекта ProductLine (Catalog.java)

public ProductLine getProductLine( String name ) { Enumeration enum = productLines.elements(); while( enum.hasMoreElements() ) { ProductLine pl = (ProductLine)enum.nextElement(); if( pl.getName().equals( name ) ) { return pl; } } return null; }

Другая операция, полезная при работе с каталогом, — получение конкретного объекта Product (товар) по его идентификатору. Эта операция позволяет отображать и редактировать отдельные элементы объекта Product. Для этого в каждом объекте, соответствующем серии товаров каталога, должен быть предусмотрен метод поиска конкретного товара. Детали реализации этого метода пока нас не интересуют, они будут рассматриваться в объекте ProductLine. Это типичный пример инкапсуляции, свойственной объектно-ориентированным языкам программирования. Листинг 6.5 иллюстрирует поиск товара по его идентификатору.





Листинг 6.5. Поиск товара в каталоге (Catalog.java)

public Product getProduct( String id ) { Enumeration enum = productLines.elements(); while( enum.hasMoreElements() ) { ProductLine pl = (ProductLine)enum.nextElement(); Product p = pl.getProduct( id ); if( p != null ) { return p; } } return null; }

Если не удалось обнаружить товар с указанным идентификатором, здесь также возвращается объект nul 1. Полезно выработать определенный принцип действия, если поиск оказался неудачным, и в таких случаях либо всегда возвращать null, либо всегда вызывать исключение. В программах, которые мы рассматриваем в этой главе, в случае неудачного поиска мы решили возвращать объект null, и всюду последовательно придерживаемся этого решения.

Объект Catalog позволяет осуществлять еще одно важное действие — удаление объектов Products. Этот метод, приведенный в листинге 6.6, аналогичен методу getProducts, но при нахождении указанного объекта он сначала удаляется из объекта ProductLine, а потом метод возвращает этот объект. Опять-таки, если объекта с указанным идентификатором не удалось обнаружить, возвращается объект null.



Листинг 6.6. Удаление товара из каталога (Catalog.java)

public Product deleteProduct( String id ) { Enumeration enum = productLines.elements(); while( enum.hasMoreElements() ) { ProductLine pl = (ProductLine)enum.nextElement(); Product p = pl.getProduct( id ); if( p != null ) { pl.deleteProduct( id ); return p; } } return null; }

Вам также необходимо, чтобы класс Catalog был способен выдавать содержащиеся в нем данные в виде документа XML. Для этого существует метод, представленный в листинге 6.7, который записывает данные с помощью объекта XMLWriter. Класс XMLWriter — служебный класс, который используется при выводе данных XML в выходной поток. Этот класс мы рассмотрим чуть позже, после класса Catal og. Как и в случае с конструктором класса Cal atog, где мы разобрали только начальную часть кода XML, которая необходима, чтобы можно было предоставить дальнейший анализ элементам ProductLine, здесь мы пишем только открывающий и закрывающий теги каталога. Запись элементов, соответствующих сериям товаров, является прерогативой самого класса ProductLine.



Листинг 6.7. Запись каталога в виде документа XML (Catalog.java)

public void toXML( XMLWriter writer ) throws IOException { writer.writeln( "<catalog>" ); writer.indent(); Enumeration enum = productLines.elements(); while( enum.hasMoreElements() ) { ProductLine pl = (ProductLine)enum.nextElement(); pl.toXML( writer ); writer.writeln( "" ); } writer.unindent(); writer.writeln( "</catalog>" ); } }

 




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