001 /* PAVLOV -- Multiple Choice Study System 002 * Copyright (C) 2000 - 2004 T.J. Willis 003 * 004 * This program is free software; you can redistribute it and/or 005 * modify it under the terms of the GNU General Public License 006 * as published by the Free Software Foundation; either version 2 007 * of the License, or (at your option) any later version. 008 * 009 * This program is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 * GNU General Public License for more details. 013 * 014 * You should have received a copy of the GNU General Public License 015 * along with this program; if not, write to the Free Software 016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. 017 * 018 * $Header: /cvsroot/pavlov/net/sourceforge/pavlov/library/BookXMLHandler.java,v 1.6 2004/07/01 05:50:20 tj_willis Exp $ 019 */ 020 package net.sourceforge.pavlov.library; 021 022 import org.xml.sax.*; 023 import org.xml.sax.helpers.*; 024 import java.io.*; 025 import java.nio.*; 026 import java.nio.charset.*; 027 import org.apache.log4j.*; 028 029 030 031 /** 032 * Implementation of Sax's DefaultHandler for Book XML files 033 * @author <a href="mailto:tj_willis@users.sourceforge.net"></a> 034 * @version 1.0 035 * @see org.xml.sax.ContentHandler 036 * @see org.xml.sax.DefaultHandler 037 */ 038 public final class BookXMLHandler extends DefaultHandler { 039 private Book bk; 040 private Chapter cp; 041 private Question q; 042 private CharArrayWriter contents = new CharArrayWriter(); 043 private StringWriter buf = new StringWriter(); 044 private int MODE_NONE = 0; 045 private int MODE_CONTENTS = 1; 046 private int MODE_TOPICS = 2; 047 private int MODE_TEXT = 3; 048 private int MODE_RIGHTANSWER = 4; 049 private int MODE_WRONGANSWER = 5; 050 private int MODE_HINT = 6; 051 private int MODE_WRONGANSWERS = 7; 052 private int mode = MODE_NONE; 053 private Category cat 054 = Category.getInstance(BookXMLHandler.class.getName()); 055 //private Charset utf8; 056 057 // Override methods of the DefaultHandler class 058 // to gain notification of SAX Events. 059 // 060 // See org.xml.sax.ContentHandler for all available events. 061 // 062 /** 063 * Called when sax starts reading the file. 064 * 065 * @exception SAXException if an error occurs 066 */ 067 public void startDocument() throws SAXException { 068 cat.setLevel(Level.WARN); 069 bk = new Book(); 070 /* 071 try { 072 utf8 = Charset.forName("UTF-8"); 073 } catch (Exception e) { 074 cat.warn("Can't get UTF-8 encoder",e); 075 utf8 = Charset.defaultCharset(); 076 }*/ 077 } 078 079 /** 080 * Called when sax ends reading the file. 081 * 082 * @exception SAXException if an error occurs 083 */ 084 public void endDocument() throws SAXException { 085 086 } 087 088 /** 089 * Called when a start tag is found. 090 * 091 * @param namespaceURI a <code>String</code> value 092 * @param localName a <code>String</code> value 093 * @param qName a <code>String</code> value 094 * @param attr an <code>Attributes</code> value 095 * @exception SAXException if an error occurs 096 */ 097 public void startElement(String namespaceURI, 098 String localName, 099 String qName, 100 Attributes attr) throws SAXException { 101 102 contents.reset(); 103 buf = new StringWriter(); //.delete(0,-1); 104 105 if (localName.equals("BOOK")) { 106 String key, value; 107 108 for (int i = 0; i < attr.getLength(); i++) { 109 key = attr.getLocalName(i); 110 value = attr.getValue(i); 111 if (key.equals("NAME")) bk.setName(value); 112 else if (key.equals("AUTHOR")) bk.setAuthor(value); 113 else if (key.equals("COVER")) bk.setCover(value); 114 } 115 } else if (localName.equals("CHAPTER")) { 116 cp = new Chapter(); 117 String key, value; 118 119 for (int i = 0; i < attr.getLength(); i++) { 120 key = attr.getLocalName(i); 121 value = attr.getValue(i); 122 if (key.equals("NAME")) cp.setName(value); 123 else if (key.equals("AUTHOR")) cp.setAuthor(value); 124 else if (key.equals("COVER")) cp.setCover(value); 125 } 126 } else if (localName.equals("QUESTION")) { 127 q = new Question(); 128 String key, value; 129 130 for (int i = 0; i < attr.getLength(); i++) { 131 key = attr.getLocalName(i); 132 value = attr.getValue(i); 133 if (key.equals("ID")) q.setId(value); 134 if (key.equals("IMG")) q.setImageFile(value); 135 if (key.equals("SOUND")) q.setSoundFile(value); 136 //else if (key.equals("DATE")) qd.setLast(value); 137 } 138 139 } else if (localName.equals("WRONGANSWER")) { 140 mode = MODE_WRONGANSWER; 141 } else if (localName.equals("WRONGANSWERS")) { 142 mode = MODE_WRONGANSWERS; 143 } else if (localName.equals("RIGHTANSWER")) { 144 mode = MODE_RIGHTANSWER; 145 146 } else if (localName.equals("CONTENTS")) { 147 mode = MODE_CONTENTS; 148 149 } else if (localName.equals("TOPICS")) { 150 mode = MODE_TOPICS; 151 152 } else if (localName.equals("TEXT")) { 153 mode = MODE_TEXT; 154 155 } else if (localName.equals("HINT")) { 156 mode = MODE_HINT; 157 }else { 158 cat.warn("Unrecognized book XML element [ " + 159 localName + " ]"); 160 161 // Also, let's print the attributes if 162 // there are any... 163 for (int i = 0; i < attr.getLength(); i++) { 164 cat.warn(" ATTRIBUTE: " + 165 attr.getLocalName(i) + 166 " VALUE: " + 167 attr.getValue(i)); 168 } 169 170 } 171 } 172 173 /** 174 * Called when an END tag is found. 175 * 176 * @param namespaceURI a <code>String</code> value 177 * @param localName a <code>String</code> value 178 * @param qName a <code>String</code> value 179 * @exception SAXException if an error occurs 180 */ 181 public void endElement(String namespaceURI, 182 String localName, 183 String qName) throws SAXException { 184 185 // n.b.: don't zero-out mode for "HINT" or "WRONGANSWER" 186 if (localName.equals("BOOK")) { 187 // do nothing 188 } else if (localName.equals("CHAPTER")) { 189 bk.addChapter(cp); 190 } else if (localName.equals("QUESTION")) { 191 cp.addQuestion(q); 192 } else if (localName.equals("HINT")) { 193 q.addHint(buf.toString()); 194 } else if (localName.equals("WRONGANSWER")) { 195 q.addWrongAnswer(encode(buf.toString())); 196 } else if (localName.equals("WRONGANSWERS")) {//q.addWrongAnswer(buf.toString()); 197 } else if (localName.equals("RIGHTANSWER")) { 198 q.setRightAnswer(encode(buf.toString())); 199 } else if (localName.equals("TOPICS")) { 200 cp.setDescription(buf.toString()); 201 } else if (localName.equals("TEXT")) { 202 q.setText( encode(buf.toString())); 203 } else if (localName.equals("CONTENTS")) { 204 bk.setDescription(buf.toString()); 205 } else { 206 cat.warn("Unrecognized Book End Element[ " + 207 localName + " ]"); 208 } 209 } 210 211 private String encode(String in){ 212 if(in==null) return null; 213 return in; 214 // ByteBuffer b = utf8.encode(in); 215 // byte arr[] = b.array(); 216 // String s = in; 217 // try { 218 // s = new String(arr,"UTF-8"); 219 // //System.out.println("encoded " + s); 220 // } catch(Exception e) { 221 // cat.warn("Exception encoding " +in,e); 222 // } 223 // return s; 224 225 } 226 227 /** 228 * Called when sax reads characters that are not start or end tags. 229 * 230 * @param ch a <code>char[]</code> value 231 * @param start an <code>int</code> value 232 * @param length an <code>int</code> value 233 * @exception SAXException if an error occurs 234 */ 235 public void characters(char[] ch, int start, int length) 236 throws SAXException { 237 //contents.write(ch, start, length); 238 buf.write(ch,start,length); 239 } 240 241 242 /** 243 * Returns the loaded book. 244 * @return a <code>Book</code> value 245 */ 246 public Book getBook() { 247 return bk; 248 } 249 } 250