00001 package edu.stanford.hci.r3.tools.design.acrobat;
00002
00003 import java.io.File;
00004 import java.io.FileNotFoundException;
00005 import java.io.FileOutputStream;
00006 import java.io.IOException;
00007 import java.util.ArrayList;
00008 import java.util.HashMap;
00009 import java.util.LinkedList;
00010 import java.util.List;
00011 import java.util.Map;
00012
00013 import javax.xml.parsers.ParserConfigurationException;
00014 import javax.xml.parsers.SAXParser;
00015 import javax.xml.parsers.SAXParserFactory;
00016
00017 import org.xml.sax.Attributes;
00018 import org.xml.sax.SAXException;
00019 import org.xml.sax.helpers.DefaultHandler;
00020
00021 import edu.stanford.hci.r3.PaperToolkit;
00022 import edu.stanford.hci.r3.paper.Region;
00023 import edu.stanford.hci.r3.units.Points;
00024 import edu.stanford.hci.r3.units.Units;
00025 import edu.stanford.hci.r3.util.SystemUtils;
00026
00039 public class RegionConfigurationWriter extends DefaultHandler {
00040
00046 private class FileNameHandler extends TagHandler {
00047
00048 public void handleStart(String qName, Attributes attributes) {
00049 if (outputXMLFile == null && qName.equals("f") && attributes.getLength() == 1) {
00050 String thePath = null;
00051 if (!SystemUtils.operatingSystemIsWindowsVariant()) {
00052 System.err
00053 .println("RegionConfigurationWriter: Sorry, we may not support "
00054 + "your operating system ("
00055 + System.getProperty("os.name")
00056 + ") at the moment. The file name handler has only been tested on Windows.");
00057 thePath = attributes.getValue(0);
00058 } else {
00059
00060
00061
00062
00063 final String notPath = attributes.getValue(0);
00064
00065
00066 String almostPath = notPath.substring(1);
00067
00068
00069
00070 thePath = almostPath.substring(0, 1) + ":" + almostPath.substring(1);
00071 }
00072
00073
00074 thePath = thePath.substring(0, thePath.lastIndexOf("."));
00075 outputXMLFile = new File(thePath + ".regions.xml");
00076 System.out.println("RegionConfigurationWriter :: Writing the Regions out to "
00077 + outputXMLFile.getAbsolutePath());
00078 }
00079 }
00080 }
00081
00092 private class RegionHandler extends TagHandler {
00093
00098 public void handleStart(String qName, Attributes attributes) {
00099 if (qName.equals("square")) {
00100 String nameOfRegion = attributes.getValue("title");
00101 String rectString = attributes.getValue("rect");
00102 String[] rectValStrings = rectString.split(",");
00103
00104 final double x = Double.parseDouble(rectValStrings[0]);
00105 final double y = Double.parseDouble(rectValStrings[1]);
00106 final double w = Double.parseDouble(rectValStrings[2]) - x;
00107 final double h = Double.parseDouble(rectValStrings[3]) - y;
00108 final Region r = new Region(nameOfRegion, new Points(x), new Points(y), new Points(
00109 w), new Points(h));
00110 temporaryRegionsList.add(r);
00111 }
00112 }
00113 }
00114
00119 private class TagHandler {
00120 public void handleEnd(String qName) {
00121
00122 }
00123
00124 public void handleStart(String qName, Attributes attributes) {
00125
00126 }
00127
00128 public void handleValue(String value) {
00129
00130 }
00131 }
00132
00137 private class WidthAndHeightHandler extends TagHandler {
00138 private boolean captureNextValue;
00139
00140 private boolean lookingForHeight;
00141
00142 private boolean lookingForWidth;
00143
00144 public void handleStart(String qName, Attributes attributes) {
00145 if (qName.equals("field") && (attributes.getLength() == 1)) {
00146 if (attributes.getValue(0).equals("Height")) {
00147 lookingForHeight = true;
00148 } else if (attributes.getValue(0).equals("Width")) {
00149 lookingForWidth = true;
00150 }
00151 } else if (qName.equals("value")) {
00152 captureNextValue = true;
00153 }
00154 }
00155
00156 public void handleValue(String value) {
00157 if (captureNextValue) {
00158 if (lookingForHeight) {
00159 heightInPoints = Double.parseDouble(value);
00160
00161 regionConfiguration.setDocumentHeight(heightInPoints);
00162 resetFlags();
00163 } else if (lookingForWidth) {
00164 widthInPoints = Double.parseDouble(value);
00165
00166 regionConfiguration.setDocumentWidth(widthInPoints);
00167 resetFlags();
00168 }
00169 }
00170 }
00171
00175 private void resetFlags() {
00176 lookingForHeight = false;
00177 lookingForWidth = false;
00178 captureNextValue = false;
00179 }
00180 }
00181
00185 private class XFDFHandler extends TagHandler {
00186 public void handleEnd(String qName) {
00187 if (!qName.equals("xfdf")) {
00188 return;
00189 }
00190
00191
00192 for (final Region r : temporaryRegionsList) {
00193
00194 final Units rh = r.getUnscaledBoundsHeight();
00195 final Units rw = r.getUnscaledBoundsWidth();
00196 final Region correctedRegion = new Region(r.getName(), r.getOriginX(), new Points(
00197 heightInPoints - r.getOriginY().getValue() - rh.getValue()), rw, rh);
00198
00199 correctedRegion.setActive(true);
00200 regionConfiguration.addRegion(correctedRegion);
00201 }
00202
00203
00204 try {
00205 final FileOutputStream fileOutputStream = new FileOutputStream(outputXMLFile);
00206 PaperToolkit.toXML(regionConfiguration, fileOutputStream);
00207 fileOutputStream.close();
00208 } catch (FileNotFoundException e) {
00209 e.printStackTrace();
00210 } catch (IOException e) {
00211 e.printStackTrace();
00212 }
00213 }
00214 }
00215
00219 private LinkedList<TagHandler> handlers = new LinkedList<TagHandler>();
00220
00224 private double heightInPoints;
00225
00229 private File inputXMLFile;
00230
00234 private File outputXMLFile;
00235
00239 private SAXParser parser;
00240
00244 private RegionConfiguration regionConfiguration = new RegionConfiguration();
00245
00250 private Map<String, TagHandler> tagToHandler = new HashMap<String, TagHandler>();
00251
00256 private List<Region> temporaryRegionsList = new ArrayList<Region>();
00257
00261 private double widthInPoints;
00262
00266 public RegionConfigurationWriter(File theInputXmlFile) {
00267 inputXMLFile = theInputXmlFile;
00268 SAXParserFactory factory = SAXParserFactory.newInstance();
00269 try {
00270 parser = factory.newSAXParser();
00271 } catch (ParserConfigurationException e) {
00272 e.printStackTrace();
00273 } catch (SAXException e) {
00274 e.printStackTrace();
00275 }
00276
00277
00278 tagToHandler.put("field", new WidthAndHeightHandler());
00279 tagToHandler.put("f", new FileNameHandler());
00280 tagToHandler.put("square", new RegionHandler());
00281 tagToHandler.put("xfdf", new XFDFHandler());
00282 }
00283
00288 public RegionConfigurationWriter(File theInputXMLFile, File theOutputXMLFile) {
00289 this(theInputXMLFile);
00290 outputXMLFile = theOutputXMLFile;
00291 }
00292
00296 @Override
00297 public void characters(char[] chars, int start, int n) throws SAXException {
00298 super.characters(chars, start, n);
00299 final String trimmedValue = new String(chars, start, n).trim();
00300
00301
00302 for (int i = handlers.size() - 1; i >= 0; i--) {
00303 handlers.get(i).handleValue(trimmedValue);
00304 }
00305 }
00306
00310 @Override
00311 public void endDocument() throws SAXException {
00312 super.endDocument();
00313 }
00314
00319 @Override
00320 public void endElement(String uri, String localName, String qName) throws SAXException {
00321 super.endElement(uri, localName, qName);
00322
00323
00324
00325 for (int i = handlers.size() - 1; i >= 0; i--) {
00326 handlers.get(i).handleEnd(qName);
00327 }
00328
00329
00330 TagHandler handler = tagToHandler.get(qName);
00331 if (handler != null) {
00332 handlers.removeLast();
00333 }
00334 }
00335
00339 public File getOutputFile() {
00340 return outputXMLFile;
00341 }
00342
00346 public void processXML() {
00347 try {
00348 parser.parse(inputXMLFile, this);
00349 } catch (SAXException e) {
00350 e.printStackTrace();
00351 } catch (IOException e) {
00352 e.printStackTrace();
00353 }
00354 }
00355
00359 @Override
00360 public void startDocument() throws SAXException {
00361 super.startDocument();
00362 }
00363
00368 @Override
00369 public void startElement(String uri, String localName, String qName, Attributes attributes)
00370 throws SAXException {
00371 super.startElement(uri, localName, qName, attributes);
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 TagHandler handler = tagToHandler.get(qName);
00384 if (handler != null) {
00385 handlers.addLast(handler);
00386 }
00387
00388
00389 for (int i = handlers.size(); i > 0; i--) {
00390 handlers.get(i - 1).handleStart(qName, attributes);
00391 }
00392 }
00393 }