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