/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Distributable under LGPL license. * See terms of license at gnu.org. */ package net.java.sip.communicator.impl.history; import java.io.*; import java.text.*; import java.util.*; import javax.xml.parsers.*; import net.java.sip.communicator.service.history.*; import net.java.sip.communicator.service.history.records.*; import org.jitsi.util.xml.XMLUtils; import org.w3c.dom.*; import org.xml.sax.*; /** * * @author Alexander Pelov */ public class DBStructSerializer { private HistoryServiceImpl historyService; /** * Constructor. * * @param historyService the history service */ public DBStructSerializer(HistoryServiceImpl historyService) { this.historyService = historyService; } /** * Write the history. * * @param dbDatFile the database file * @param history the history to write * @throws IOException if write failed for any reason */ public void writeHistory(File dbDatFile, History history) throws IOException { DocumentBuilder builder = this.historyService.getDocumentBuilder(); Document doc = builder.newDocument(); Element root = doc.createElement("dbstruct"); root.setAttribute("version", "1.0"); Element structure = this.createStructureTag(doc, history .getHistoryRecordsStructure()); Element id = this.createIDTag(doc, history.getID()); root.appendChild(structure); root.appendChild(id); doc.appendChild(root); XMLUtils.writeXML(doc, dbDatFile); } private Element createIDTag(Document doc, HistoryID historyID) { Element idroot = doc.createElement("id"); Element current = idroot; String[] idelements = historyID.getID(); for (int i = 0; i < idelements.length; i++) { Element idnode = doc.createElement("component"); idnode.setAttribute("value", idelements[i]); current.appendChild(idnode); current = idnode; } return idroot; } private Element createStructureTag(Document doc, HistoryRecordStructure recordStructure) { Element structure = doc.createElement("structure"); String[] propertyNames = recordStructure.getPropertyNames(); int count = recordStructure.getPropertyCount(); for (int i = 0; i < count; i++) { Element property = doc.createElement("property"); property.setAttribute("name", propertyNames[i]); structure.appendChild(property); } return structure; } /** * This method parses an XML file, and returns a History object created with * the information from it. The parsing is non-validating, so if a malformed * XML is passed the results are undefined. The file should be with the * following structure: * * * * * * @param dbDatFile * The file to be parsed. * @return A History object corresponding to this dbstruct file. * @throws SAXException * Thrown if an error occurs during XML parsing. * @throws IOException * Thrown if an IO error occurs. * @throws ParseException * Thrown if there is error in the XML data format. */ public History loadHistory(File dbDatFile) throws SAXException, IOException, ParseException { Document doc = historyService.parse(dbDatFile); Node root = doc.getFirstChild(); HistoryID id = loadID(root); HistoryRecordStructure structure = loadStructure(root); return new HistoryImpl(id, dbDatFile.getParentFile(), structure, historyService); } /** * This method parses a "structure" tag and returns the corresponging * HistoryRecordStructure. * * @throws ParseException * Thrown if there is no structure tag. */ private HistoryRecordStructure loadStructure(Node root) throws ParseException { Element structNode = findElement(root, "structure"); if (structNode == null) { throw new ParseException("There is no structure tag defined!", 0); } NodeList nodes = structNode.getChildNodes(); int count = nodes.getLength(); ArrayList propertyNames = new ArrayList(count); for (int i = 0; i < count; i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE && "property".equals(node.getNodeName())) { Element parameter = (Element) node; String paramName = parameter.getAttribute("name"); if (paramName == null) { continue; } propertyNames.add(paramName); } } String[] names = new String[propertyNames.size()]; propertyNames.toArray(names); return new HistoryRecordStructure(names); } private HistoryID loadID(Node parent) throws ParseException { Element idnode = findElement(parent, "id"); ArrayList al = loadID(new ArrayList(), idnode); String[] id = new String[al.size()]; al.toArray(id); return HistoryID.createFromID(id); } private ArrayList loadID(ArrayList loadedIDs, Node parent) throws ParseException { Element node = findElement(parent, "component"); if (node != null) { String idValue = node.getAttribute("value"); if (idValue != null) { loadedIDs.add(idValue); } else { throw new ParseException( "There is an ID object without value.", 0); } } else { // no more nodes return loadedIDs; } return loadID(loadedIDs, node); } /** * This method seraches through all children of a given node and returns the * first with the name matching the given one. If no node is found, null is * returned. */ private Element findElement(Node parent, String name) { Element retVal = null; NodeList nodes = parent.getChildNodes(); int count = nodes.getLength(); for (int i = 0; i < count; i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE && name.equals(node.getNodeName())) { retVal = (Element) node; break; } } return retVal; } }