| 1 | /*
|
|---|
| 2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|---|
| 3 | *
|
|---|
| 4 | * Copyright 2008 jOpenDocument, by ILM Informatique. All rights reserved.
|
|---|
| 5 | *
|
|---|
| 6 | * The contents of this file are subject to the terms of the GNU
|
|---|
| 7 | * General Public License Version 3 only ("GPL").
|
|---|
| 8 | * You may not use this file except in compliance with the License.
|
|---|
| 9 | * You can obtain a copy of the License at http://www.gnu.org/licenses/gpl-3.0.html
|
|---|
| 10 | * See the License for the specific language governing permissions and limitations under the License.
|
|---|
| 11 | *
|
|---|
| 12 | * When distributing the software, include this License Header Notice in each file.
|
|---|
| 13 | *
|
|---|
| 14 | */
|
|---|
| 15 |
|
|---|
| 16 | package org.jopendocument.io;
|
|---|
| 17 |
|
|---|
| 18 | import java.util.Stack;
|
|---|
| 19 |
|
|---|
| 20 | import org.jopendocument.model.office.OfficeBody;
|
|---|
| 21 | import org.jopendocument.model.office.OfficeSpreadsheet;
|
|---|
| 22 | import org.jopendocument.model.table.TableTable;
|
|---|
| 23 | import org.jopendocument.model.table.TableTableCell;
|
|---|
| 24 | import org.jopendocument.model.table.TableTableColumn;
|
|---|
| 25 | import org.jopendocument.model.table.TableTableRow;
|
|---|
| 26 | import org.jopendocument.model.text.TextP;
|
|---|
| 27 | import org.jopendocument.model.text.TextSpan;
|
|---|
| 28 | import org.xml.sax.Attributes;
|
|---|
| 29 | import org.xml.sax.helpers.DefaultHandler;
|
|---|
| 30 |
|
|---|
| 31 | public class SaxContentUnmarshaller extends DefaultHandler {
|
|---|
| 32 |
|
|---|
| 33 | private OfficeBody body;
|
|---|
| 34 |
|
|---|
| 35 | private Object current;
|
|---|
| 36 |
|
|---|
| 37 | private final Stack<Object> stack;
|
|---|
| 38 |
|
|---|
| 39 | // -----
|
|---|
| 40 |
|
|---|
| 41 | public SaxContentUnmarshaller() {
|
|---|
| 42 | this.stack = new Stack<>();
|
|---|
| 43 | }
|
|---|
| 44 |
|
|---|
| 45 | // ----- callbacks: -----
|
|---|
| 46 |
|
|---|
| 47 | private void assertParsed(final Attributes attribs, final int l) {
|
|---|
| 48 | if (attribs.getLength() > l) {
|
|---|
| 49 | for (int i = 0; i < attribs.getLength(); i++) {
|
|---|
| 50 | System.err.println(attribs.getQName(i) + " -> " + attribs.getValue(i));
|
|---|
| 51 | }
|
|---|
| 52 | throw new IllegalStateException("Somme attributes are not parsed");
|
|---|
| 53 | }
|
|---|
| 54 | }
|
|---|
| 55 |
|
|---|
| 56 | public void characters(final char[] data, final int start, final int length) {
|
|---|
| 57 | final StringBuffer s = new StringBuffer();
|
|---|
| 58 | s.append(data, start, length);
|
|---|
| 59 | if (this.current instanceof TextP) {
|
|---|
| 60 | ((TextP) this.current).addToLastTextSpan(s.toString());
|
|---|
| 61 | } else if (this.current instanceof TextSpan) {
|
|---|
| 62 | ((TextSpan) this.current).concantValue(s.toString());
|
|---|
| 63 | }
|
|---|
| 64 | }
|
|---|
| 65 |
|
|---|
| 66 | // -----
|
|---|
| 67 |
|
|---|
| 68 | public void endElement(final String uri, final String localName, final String qName) {
|
|---|
| 69 | this.pop();
|
|---|
| 70 | }
|
|---|
| 71 |
|
|---|
| 72 | // -----
|
|---|
| 73 |
|
|---|
| 74 | public OfficeBody getBody() {
|
|---|
| 75 | return this.body;
|
|---|
| 76 | }
|
|---|
| 77 |
|
|---|
| 78 | // -----
|
|---|
| 79 |
|
|---|
| 80 | private void pop() {
|
|---|
| 81 |
|
|---|
| 82 | if (!this.stack.isEmpty()) {
|
|---|
| 83 | this.stack.pop();
|
|---|
| 84 |
|
|---|
| 85 | }
|
|---|
| 86 | if (!this.stack.isEmpty()) {
|
|---|
| 87 | this.current = this.stack.peek();
|
|---|
| 88 | }
|
|---|
| 89 | }
|
|---|
| 90 |
|
|---|
| 91 | private void push(final Object o) {
|
|---|
| 92 | this.current = o;
|
|---|
| 93 | this.stack.push(o);
|
|---|
| 94 |
|
|---|
| 95 | }
|
|---|
| 96 |
|
|---|
| 97 | public void startElement(final String uri, final String localName, final String qName, final Attributes attribs) {
|
|---|
| 98 |
|
|---|
| 99 | if (qName.equals("office:automatic-styles")) {
|
|---|
| 100 | /*this.autostyles = new OfficeAutomaticStyles();
|
|---|
| 101 | this.document.setAutomaticStyles(this.autostyles);
|
|---|
| 102 | this.push(this.autostyles);*/
|
|---|
| 103 | this.push(new Object());
|
|---|
| 104 | } else if (qName.equals("style:style")) {
|
|---|
| 105 | final Object style = new Object();
|
|---|
| 106 | /*final StyleStyle style = new StyleStyle();
|
|---|
| 107 | style.setStyleName(attribs.getValue("style:name"));
|
|---|
| 108 | style.setStyleFamily(attribs.getValue("style:family"));
|
|---|
| 109 | style.setStyleParentStyleName(attribs.getValue("style:parent-style-name"));
|
|---|
| 110 | style.setMasterPageName(attribs.getValue("style:master-page-name"));
|
|---|
| 111 |
|
|---|
| 112 | // style:data-style-name="N108"
|
|---|
| 113 | if (this.current instanceof OfficeAutomaticStyles) {
|
|---|
| 114 | this.autostyles.addStyle(style);
|
|---|
| 115 | } else {
|
|---|
| 116 | System.err.println("Not OfficeAutomaticStyles:" + this.current);
|
|---|
| 117 | Thread.dumpStack();
|
|---|
| 118 | }*/
|
|---|
| 119 | this.push(style);
|
|---|
| 120 | } else if (qName.equals("number:number-style")) {
|
|---|
| 121 | final Object style = new Object();
|
|---|
| 122 | /*final NumberNumberStyle style = new NumberNumberStyle();
|
|---|
| 123 | style.setStyleName(attribs.getValue("style:name"));
|
|---|
| 124 | style.setStyleFamily(attribs.getValue("style:family"));
|
|---|
| 125 |
|
|---|
| 126 | // style:data-style-name="N108"
|
|---|
| 127 | if (this.current instanceof OfficeAutomaticStyles) {
|
|---|
| 128 | this.autostyles.addStyle(style);
|
|---|
| 129 | } else {
|
|---|
| 130 | System.err.println("Not OfficeAutomaticStyles:" + this.current);
|
|---|
| 131 | Thread.dumpStack();
|
|---|
| 132 | }*/
|
|---|
| 133 | this.push(style);
|
|---|
| 134 | } else if (qName.equals("style:table-row-properties")) {
|
|---|
| 135 | final Object props = new Object();
|
|---|
| 136 | /*final StyleTableRowProperties props = new StyleTableRowProperties();
|
|---|
| 137 | props.setFoBreakBefore(attribs.getValue("fo:break-before"));
|
|---|
| 138 | props.setRowHeight(attribs.getValue("style:row-height"));
|
|---|
| 139 | //props.setUseOptimalRowHeight(attribs.getValue("style:use-optimal-row-height"));
|
|---|
| 140 | if (this.current instanceof StyleStyle) {
|
|---|
| 141 | ((StyleStyle) this.current).setTableRowProperties(props);
|
|---|
| 142 | } else {
|
|---|
| 143 | System.err.println("Not StyleStyle:" + this.current);
|
|---|
| 144 | Thread.dumpStack();
|
|---|
| 145 | }*/
|
|---|
| 146 | this.push(props);
|
|---|
| 147 | } else if (qName.equals("style:table-properties")) {
|
|---|
| 148 | //final StyleTableProperties props = new StyleTableProperties();
|
|---|
| 149 | final Object props = new Object();
|
|---|
| 150 | //props.setDisplay(ValueHelper.getBoolean(attribs.getValue("table:display")));
|
|---|
| 151 | //props.setWritingMode(attribs.getValue("style:writing-mode"));
|
|---|
| 152 |
|
|---|
| 153 | /*if (this.current instanceof StyleStyle) {
|
|---|
| 154 | ((StyleStyle) this.current).setTableProperties(props);
|
|---|
| 155 | } else {
|
|---|
| 156 | System.err.println("Not StyleStyle:" + this.current);
|
|---|
| 157 | Thread.dumpStack();
|
|---|
| 158 | }*/
|
|---|
| 159 | this.push(props);
|
|---|
| 160 | } else if (qName.equals("style:table-cell-properties")) {
|
|---|
| 161 | final Object props = new Object();
|
|---|
| 162 | /*final StyleTableCellProperties props = new StyleTableCellProperties();
|
|---|
| 163 | props.setVerticalAlign(attribs.getValue("style:vertical-align"));
|
|---|
| 164 | props.setBackgroundColor(attribs.getValue("fo:background-color"));
|
|---|
| 165 |
|
|---|
| 166 | props.setPadding(attribs.getValue("fo:padding"));
|
|---|
| 167 |
|
|---|
| 168 | props.setTextAlignSource(attribs.getValue("style:text-align-source"));
|
|---|
| 169 | props.setRepeatContent(attribs.getValue("style:repeat-content"));
|
|---|
| 170 |
|
|---|
| 171 | props.setBorderLeft(attribs.getValue("fo:border-left"));
|
|---|
| 172 | props.setBorderRight(attribs.getValue("fo:border-right"));
|
|---|
| 173 |
|
|---|
| 174 | props.setBorderTop(attribs.getValue("fo:border-top"));
|
|---|
| 175 | props.setBorderBottom(attribs.getValue("fo:border-bottom"));
|
|---|
| 176 | // doit etre apres pour overrider le border!
|
|---|
| 177 | props.setBorder(attribs.getValue("fo:border"));
|
|---|
| 178 | props.setWrapOption(attribs.getValue("fo:wrap-option"));
|
|---|
| 179 | if (this.current instanceof StyleStyle) {
|
|---|
| 180 | ((StyleStyle) this.current).setTableCellProperties(props);
|
|---|
| 181 |
|
|---|
| 182 | } else {
|
|---|
| 183 | System.err.println("Not StyleStyle:" + this.current);
|
|---|
| 184 | Thread.dumpStack();
|
|---|
| 185 | }*/
|
|---|
| 186 | this.push(props);
|
|---|
| 187 | } else if (qName.equals("style:text-properties")) {
|
|---|
| 188 | final Object props = new Object();
|
|---|
| 189 | /*final StyleTextProperties props = new StyleTextProperties();
|
|---|
| 190 | props.setFontName(attribs.getValue("style:font-name"));
|
|---|
| 191 | props.setFontSize(attribs.getValue("fo:font-size"));
|
|---|
| 192 | props.setFontWeight(attribs.getValue("fo:font-weight"));
|
|---|
| 193 | props.setColor(attribs.getValue("fo:color"));
|
|---|
| 194 | // fo:hyphenate="true"
|
|---|
| 195 | if (this.current instanceof StyleStyle) {
|
|---|
| 196 | ((StyleStyle) this.current).setTextProperties(props);
|
|---|
| 197 | } else {
|
|---|
| 198 | System.err.println("Not StyleStyle:" + this.current);
|
|---|
| 199 | Thread.dumpStack();
|
|---|
| 200 | }*/
|
|---|
| 201 | this.push(props);
|
|---|
| 202 | } else if (qName.equals("style:table-column-properties")) {
|
|---|
| 203 | final Object props = new Object();
|
|---|
| 204 | /*final StyleTableColumnProperties props = new StyleTableColumnProperties();
|
|---|
| 205 | props.setFoBreakBefore(attribs.getValue("fo:break-before"));
|
|---|
| 206 | props.setStyleColumnWidth(attribs.getValue("style:column-width"));
|
|---|
| 207 |
|
|---|
| 208 | if (this.current instanceof StyleStyle) {
|
|---|
| 209 | ((StyleStyle) this.current).setTableColumnProperties(props);
|
|---|
| 210 | } else {
|
|---|
| 211 | System.err.println("Not StyleStyle:" + this.current);
|
|---|
| 212 | Thread.dumpStack();
|
|---|
| 213 | }*/
|
|---|
| 214 | this.push(props);
|
|---|
| 215 | } else if (qName.equals("style:paragraph-properties")) {
|
|---|
| 216 | final Object props = new Object();
|
|---|
| 217 | /*final StyleParagraphProperties props = new StyleParagraphProperties();
|
|---|
| 218 | props.setTextAlign(attribs.getValue("fo:text-align"));
|
|---|
| 219 | props.setMarginLeft(attribs.getValue("fo:margin-left"));
|
|---|
| 220 |
|
|---|
| 221 | if (this.current instanceof StyleStyle) {
|
|---|
| 222 | ((StyleStyle) this.current).setParagraphProperties(props);
|
|---|
| 223 | } else {
|
|---|
| 224 | System.err.println("Not StyleStyle:" + this.current);
|
|---|
| 225 | Thread.dumpStack();
|
|---|
| 226 | }*/
|
|---|
| 227 | this.push(props);
|
|---|
| 228 | } else if (qName.equals("office:body")) {
|
|---|
| 229 | this.body = new OfficeBody();
|
|---|
| 230 | this.push(this.body);
|
|---|
| 231 | } else if (qName.equals("office:spreadsheet")) {
|
|---|
| 232 | final OfficeSpreadsheet spread = new OfficeSpreadsheet();
|
|---|
| 233 | if (this.current instanceof OfficeBody) {
|
|---|
| 234 | ((OfficeBody) this.current).addOfficeSpreadsheet(spread);
|
|---|
| 235 | } else {
|
|---|
| 236 | System.err.println("Not StyleStyle:" + this.current);
|
|---|
| 237 | Thread.dumpStack();
|
|---|
| 238 | }
|
|---|
| 239 |
|
|---|
| 240 | this.push(spread);
|
|---|
| 241 |
|
|---|
| 242 | } else if (qName.equals("table:table")) {
|
|---|
| 243 | final TableTable table = new TableTable();
|
|---|
| 244 | final String printranges = attribs.getValue("table:print-ranges");
|
|---|
| 245 | if (printranges != null) {
|
|---|
| 246 | table.setTablePrintRanges(printranges);
|
|---|
| 247 | }
|
|---|
| 248 | this.assertParsed(attribs, 3);
|
|---|
| 249 | if (this.current instanceof OfficeSpreadsheet) {
|
|---|
| 250 | ((OfficeSpreadsheet) this.current).addTable(table);
|
|---|
| 251 | } else {
|
|---|
| 252 | System.err.println("Not OfficeSpreadsheet:" + this.current);
|
|---|
| 253 | Thread.dumpStack();
|
|---|
| 254 | }
|
|---|
| 255 | this.push(table);
|
|---|
| 256 |
|
|---|
| 257 | } else if (qName.equals("table:table-column")) {
|
|---|
| 258 | final TableTableColumn col = new TableTableColumn();
|
|---|
| 259 | col.setTableStyleName(attribs.getValue("table:style-name"));
|
|---|
| 260 | col.setTableDefaultCellStyleName(attribs.getValue("table:default-cell-style-name"));
|
|---|
| 261 | col.setTableNumberColumnsRepeated(attribs.getValue("table:number-columns-repeated"));
|
|---|
| 262 |
|
|---|
| 263 | this.assertParsed(attribs, 3);
|
|---|
| 264 | if (this.current instanceof TableTable) {
|
|---|
| 265 | ((TableTable) this.current).addColumn(col);
|
|---|
| 266 | } else {
|
|---|
| 267 | System.err.println("Not TableTable:" + this.current);
|
|---|
| 268 | Thread.dumpStack();
|
|---|
| 269 | }
|
|---|
| 270 | this.push(col);
|
|---|
| 271 |
|
|---|
| 272 | } else if (qName.equals("table:table-row")) {
|
|---|
| 273 |
|
|---|
| 274 | final TableTableRow row = new TableTableRow();
|
|---|
| 275 | row.setTableNumberRowsRepeated(attribs.getValue("table:number-rows-repeated"));
|
|---|
| 276 |
|
|---|
| 277 | if (this.current instanceof TableTable) {
|
|---|
| 278 | ((TableTable) this.current).addRow(row);
|
|---|
| 279 | } else {
|
|---|
| 280 | System.err.println("Not TableTable:" + this.current);
|
|---|
| 281 | }
|
|---|
| 282 | this.push(row);
|
|---|
| 283 |
|
|---|
| 284 | } else if (qName.equals("table:table-cell") || qName.equals("table:covered-table-cell")) {
|
|---|
| 285 | final TableTableCell cell = new TableTableCell();
|
|---|
| 286 | cell.setTableStyleName(attribs.getValue("table:style-name"));
|
|---|
| 287 | cell.setTableNumberColumnsRepeated(attribs.getValue("table:number-columns-repeated"));
|
|---|
| 288 | //cell.setTableNumberColumnsSpanned(attribs.getValue("table:number-columns-spanned"));
|
|---|
| 289 | //cell.setTableNumberRowsSpanned(attribs.getValue("table:number-rows-spanned"));
|
|---|
| 290 | //cell.setTableValueType(attribs.getValue("office:value-type"));
|
|---|
| 291 |
|
|---|
| 292 | if (this.current instanceof TableTableRow) {
|
|---|
| 293 | ((TableTableRow) this.current).addCell(cell);
|
|---|
| 294 | } else {
|
|---|
| 295 | System.err.println("Not TableTableRow:" + this.current);
|
|---|
| 296 | Thread.dumpStack();
|
|---|
| 297 | }
|
|---|
| 298 | this.push(cell);
|
|---|
| 299 |
|
|---|
| 300 | } else if (qName.equals("text:p")) {
|
|---|
| 301 | final TextP p = new TextP();
|
|---|
| 302 | // TODO: gerer le multi textp dans une cellule
|
|---|
| 303 | if (this.current instanceof TableTableCell) {
|
|---|
| 304 | ((TableTableCell) this.current).setTextP(p);
|
|---|
| 305 | } /*else if (this.current instanceof DrawImage) {
|
|---|
| 306 | ((DrawImage) this.current).setTextP(p);
|
|---|
| 307 | }*/ else {
|
|---|
| 308 | System.err.println("Not TableTableCell:" + this.current + " classe:" + this.current.getClass());
|
|---|
| 309 | Thread.dumpStack();
|
|---|
| 310 | }
|
|---|
| 311 | this.push(p);
|
|---|
| 312 |
|
|---|
| 313 | } else if (qName.equals("text:span")) {
|
|---|
| 314 | final TextSpan textspan = new TextSpan();
|
|---|
| 315 |
|
|---|
| 316 | if (this.current instanceof TextP) {
|
|---|
| 317 | ((TextP) this.current).addTextSpan(textspan);
|
|---|
| 318 | } else {
|
|---|
| 319 | System.err.println("Not TextP:" + this.current);
|
|---|
| 320 | Thread.dumpStack();
|
|---|
| 321 | }
|
|---|
| 322 | this.push(textspan);
|
|---|
| 323 |
|
|---|
| 324 | } /*else if (qName.equals("draw:frame")) {
|
|---|
| 325 | final DrawFrame p = new DrawFrame();
|
|---|
| 326 | p.setSvgWidth(attribs.getValue("svg:width"));
|
|---|
| 327 | p.setSvgHeight(attribs.getValue("svg:height"));
|
|---|
| 328 | p.setSvgX(attribs.getValue("svg:x"));
|
|---|
| 329 | p.setSvgY(attribs.getValue("svg:y"));
|
|---|
| 330 |
|
|---|
| 331 | if (this.current instanceof TableTableCell) {
|
|---|
| 332 | ((TableTableCell) this.current).addDrawFrame(p);
|
|---|
| 333 | } else if (this.current instanceof TableShapes) {
|
|---|
| 334 | ((TableShapes) this.current).addDrawFrame(p);
|
|---|
| 335 | } else {
|
|---|
| 336 | System.err.println("Not TableTableCell:" + this.current);
|
|---|
| 337 | Thread.dumpStack();
|
|---|
| 338 | }
|
|---|
| 339 | this.push(p);
|
|---|
| 340 |
|
|---|
| 341 | } else if (qName.equals("draw:image")) {
|
|---|
| 342 | final DrawImage p = new DrawImage();
|
|---|
| 343 | final String link = attribs.getValue("xlink:href");
|
|---|
| 344 | p.setXlinkHref(link);
|
|---|
| 345 | this.document.preloadImage(link);
|
|---|
| 346 | if (this.current instanceof DrawFrame) {
|
|---|
| 347 | ((DrawFrame) this.current).setDrawImage(p);
|
|---|
| 348 | } else {
|
|---|
| 349 | System.err.println("Not DrawFrame:" + this.current);
|
|---|
| 350 | Thread.dumpStack();
|
|---|
| 351 | }
|
|---|
| 352 | this.push(p);
|
|---|
| 353 |
|
|---|
| 354 | } else if (qName.equals("table:shapes")) {
|
|---|
| 355 | final TableShapes p = new TableShapes();
|
|---|
| 356 |
|
|---|
| 357 | if (this.current instanceof TableTable) {
|
|---|
| 358 | ((TableTable) this.current).setTableShapes(p);
|
|---|
| 359 | } else {
|
|---|
| 360 | System.err.println("Not TableTable:" + this.current);
|
|---|
| 361 | Thread.dumpStack();
|
|---|
| 362 | }
|
|---|
| 363 | this.push(p);
|
|---|
| 364 |
|
|---|
| 365 | } else if (qName.equals("office:scripts")) {
|
|---|
| 366 | this.scripts = new OfficeScripts();
|
|---|
| 367 |
|
|---|
| 368 | this.push(this.scripts);
|
|---|
| 369 |
|
|---|
| 370 | } else if (qName.equals("office:font-face-decls")) {
|
|---|
| 371 | this.fontDeclarations = new FontFaceDecls();
|
|---|
| 372 |
|
|---|
| 373 | this.push(this.fontDeclarations);
|
|---|
| 374 |
|
|---|
| 375 | } else if (qName.equals("style:font-face")) {
|
|---|
| 376 | final StyleFontFace p = new StyleFontFace();
|
|---|
| 377 | p.setStyleName(attribs.getValue("style:name"));
|
|---|
| 378 | p.setFontFamily(attribs.getValue("svg:font-family"));
|
|---|
| 379 | p.setFontFamilyGeneric(attribs.getValue("style:font-family-generic"));
|
|---|
| 380 | p.setFontPitch(attribs.getValue("style:font-pitch"));
|
|---|
| 381 |
|
|---|
| 382 | if (this.current instanceof FontFaceDecls) {
|
|---|
| 383 | ((FontFaceDecls) this.current).addFontFace(p);
|
|---|
| 384 | } else {
|
|---|
| 385 | System.err.println("Not FontFaceDecls:" + this.current);
|
|---|
| 386 | Thread.dumpStack();
|
|---|
| 387 | }
|
|---|
| 388 | this.push(p);
|
|---|
| 389 |
|
|---|
| 390 | }*/
|
|---|
| 391 |
|
|---|
| 392 | else {
|
|---|
| 393 | //System.err.println("content.xml : ignoring :" + qName);
|
|---|
| 394 | this.push(uri);
|
|---|
| 395 |
|
|---|
| 396 | }
|
|---|
| 397 | }
|
|---|
| 398 |
|
|---|
| 399 | }
|
|---|