PageRenderTime 32ms CodeModel.GetById 2ms app.highlight 24ms RepoModel.GetById 2ms app.codeStats 0ms

/src/enoa/handler/DocumentHandler.java

http://mp-rechnungs-und-kundenverwaltung.googlecode.com/
Java | 617 lines | 415 code | 52 blank | 150 comment | 94 complexity | ac89f902ab03e5cf3619223e91613da2 MD5 | raw file
  1/*
  2 *  This file is part of YaBS.
  3 *
  4 *      YaBS is free software: you can redistribute it and/or modify
  5 *      it under the terms of the GNU General Public License as published by
  6 *      the Free Software Foundation, either version 3 of the License, or
  7 *      (at your option) any later version.
  8 *
  9 *      YaBS is distributed in the hope that it will be useful,
 10 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12 *      GNU General Public License for more details.
 13 *
 14 *      You should have received a copy of the GNU General Public License
 15 *      along with YaBS.  If not, see <http://www.gnu.org/licenses/>.
 16 */
 17package enoa.handler;
 18
 19import ag.ion.bion.officelayer.document.DocumentDescriptor;
 20import ag.ion.bion.officelayer.document.DocumentException;
 21import ag.ion.bion.officelayer.document.IDocument;
 22import ag.ion.bion.officelayer.filter.*;
 23import ag.ion.bion.officelayer.form.IFormComponent;
 24import ag.ion.bion.officelayer.text.ITextCursor;
 25import ag.ion.bion.officelayer.text.ITextDocument;
 26import ag.ion.bion.officelayer.text.ITextField;
 27import ag.ion.bion.officelayer.text.ITextFieldService;
 28import ag.ion.bion.officelayer.text.IVariableTextFieldMaster;
 29import ag.ion.bion.officelayer.text.TextException;
 30import ag.ion.noa.NOAException;
 31import ag.ion.noa.filter.OpenDocumentFilter;
 32import com.sun.star.awt.XTextComponent;
 33import com.sun.star.beans.PropertyValue;
 34import com.sun.star.beans.XPropertySet;
 35import com.sun.star.form.XFormComponent;
 36import com.sun.star.frame.XStorable;
 37import com.sun.star.io.IOException;
 38import com.sun.star.uno.UnoRuntime;
 39import enoa.connection.NoaConnection;
 40import enoa.connection.URLAdapter;
 41import java.io.File;
 42import java.io.FileFilter;
 43import java.io.FileInputStream;
 44import java.io.FileNotFoundException;
 45import java.io.FileOutputStream;
 46import java.io.InputStream;
 47import java.net.MalformedURLException;
 48import java.net.UnknownHostException;
 49import java.util.ArrayList;
 50import java.util.Arrays;
 51import java.util.HashMap;
 52import java.util.Iterator;
 53import java.util.List;
 54import javax.swing.table.TableModel;
 55import mpv5.db.objects.Template;
 56import mpv5.db.objects.User;
 57import mpv5.globals.GlobalSettings;
 58import mpv5.logging.Log;
 59import org.jopendocument.util.StringInputStream;
 60
 61/**
 62 * This class OpenOffice Documents IO
 63 */
 64public class DocumentHandler {
 65
 66    /**
 67     * All known OO file extensions
 68     */
 69    public static final String EXTENSION = ".*ott$|.*sxw$|.*doc$|.*xls$|.*odt$|.*ods$|.*pps$|.*odt$|.*ppt$|.*odp$";
 70    /**
 71     * A FileFilter looking for OO files
 72     */
 73    public static FileFilter OFFICE_FILE_FILTER = new FileFilter() {
 74
 75        @Override
 76        public boolean accept(File pathname) {
 77            return pathname.getName().matches(EXTENSION);
 78        }
 79    };
 80    private final NoaConnection connection;
 81    private final DocumentDescriptor descriptor;
 82    private IDocument document;
 83    private ITextFieldService textFieldService;
 84    private ITextField[] placeholders;
 85    private TableHandler tablehandler;
 86    private File file;
 87
 88    /**
 89     * Creates a new (hidden) Document Handler on top of the given connection
 90     * @param connection The OO connection to use
 91     */
 92    public DocumentHandler(NoaConnection connection) {
 93        if (connection != null) {
 94            this.connection = connection;
 95            descriptor = DocumentDescriptor.DEFAULT_HIDDEN;
 96        } else {
 97            throw new NullPointerException("Connection cannot be null");
 98        }
 99    }
100
101    /**
102     * Load an existing document into the Document Handler
103     * @param file The file to load
104     * @param asTemplate If true, the file is treatened as template (.ott)
105     * @throws Exception Any error thrown
106     */
107    public void loadDocument(File file, boolean asTemplate) throws Exception {
108        if (!OFFICE_FILE_FILTER.accept(file)) {
109            throw new UnsupportedOperationException("The file extension must match: " + EXTENSION);
110        }
111        if (asTemplate) {
112            descriptor.setAsTemplate(asTemplate);
113        }
114        this.file = file;
115        descriptor.setHidden(true);
116        clear();
117    }
118
119    /**
120     * Creates a new, empty text document (.odt)
121     * @throws Exception
122     */
123    public void newTextDocument() throws Exception {
124        IDocument d = connection.getDocumentService().constructNewDocument(IDocument.WRITER, descriptor);
125        document = (ITextDocument) d;
126    }
127
128    /**
129     * Save the given document to the physical location of the given file.
130     * @param file
131     * @throws DocumentException
132     */
133    public synchronized void saveAs(File file) throws DocumentException {
134
135        if (file.exists()) {
136            file.delete();
137        }
138
139        document.reformat();
140        document.update();
141
142        if (file.getName().split("\\.").length < 2) {
143            throw new UnsupportedOperationException("The file must have an extension: " + file);
144        }
145
146        IFilter filter = null;
147        String extension = file.getName().substring(file.getName().lastIndexOf("."), file.getName().length());
148        if (extension.equalsIgnoreCase(".pdf")) {
149            filter = PDFFilter.FILTER;
150        } else if (extension.equalsIgnoreCase(".doc")) {
151            filter = MSOffice97Filter.FILTER;
152        } else if (extension.equalsIgnoreCase(".txt")) {
153            filter = TextFilter.FILTER;
154        } else if (extension.equalsIgnoreCase(".odt")) {
155            filter = OpenDocumentFilter.FILTER;
156        } else if (extension.equalsIgnoreCase(".html")) {
157            filter = HTMLFilter.FILTER;
158        }
159
160
161        if (filter != null) {
162            try {
163                Log.Debug(this, "Exporting to: " + file);
164                document.getPersistenceService().export(new FileOutputStream(file), filter);
165
166            } catch (Exception ex) {
167                Log.Debug(ex);
168            }
169        } else {
170            throw new UnsupportedOperationException("File extension not supported: " + extension);
171        }
172    }
173
174    /**
175     * Close the underlying doc
176     */
177    public void close() {
178        document.close();
179    }
180
181    /**
182     * Fill the Form Fields of the template with values
183     * @param data
184     * @throws Exception
185     * @throws NOAException
186     * @deprecated  slow :-/
187     */
188    public synchronized void fillFormFields(HashMap<String, Object> data) throws Exception, NOAException {
189        Log.Debug(this, "Looking for form fields in: " + document);
190        IFormComponent[] formComponents = document.getFormService().getFormComponents();
191        Iterator<String> keys = data.keySet().iterator();
192        String key = null;
193        while (keys.hasNext()) {
194
195            // get column name
196            key = keys.next();
197//            Log.Debug(this, "Found key: " + key + " [" + data.get(key) + "]");
198            for (int i = 0; i < formComponents.length; i++) {
199
200                XFormComponent xFormComponent = formComponents[i].getXFormComponent();
201                XTextComponent xTextComponent = formComponents[i].getXTextComponent();
202                XPropertySet propertySet = UnoRuntime.queryInterface(XPropertySet.class,
203                        xFormComponent);
204
205                if (propertySet != null && propertySet.getPropertySetInfo().hasPropertyByName("Name")) {
206                    String n = propertySet.getPropertyValue("Name").toString();
207//                    Log.Debug(this, "Found form field: " + n);
208                    if (n.equalsIgnoreCase(key) || key.endsWith(n)) {
209                        Log.Debug(this, "Form field matches key: " + key + " [" + data.get(key) + "]");
210                        xTextComponent.setText(String.valueOf(data.get(key)));
211                    }
212                }
213            }
214//            textDocument.getTextFieldService().refresh();
215        }
216    }
217
218    /**
219     * Fill the Placeholder Fields of the template with values
220     * @param data
221     * @throws Exception
222     * @throws NOAException
223     */
224    public synchronized void fillPlaceholderFields(HashMap<String, Object> data) throws Exception, NOAException {
225        Log.Debug(this, "Looking for placeholder fields in: " + document);
226        Iterator<String> keys = data.keySet().iterator();
227        String key = null;
228        String[] placehrepr = new String[0];
229        List<ITextField> fields = new ArrayList<ITextField>();
230        if (textFieldService == null || placeholders == null) {
231            textFieldService = ((ITextDocument) document).getTextFieldService();
232            placeholders = textFieldService.getPlaceholderFields();
233            placehrepr = new String[placeholders.length];
234            for (int i = 0; i < placeholders.length; i++) {
235                placehrepr[i] = placeholders[i].getDisplayText();
236                fields.add(placeholders[i]);
237            }
238            Log.Debug(this, "Got: " + Arrays.asList(placehrepr));
239        }
240        InputStream is = null;
241        ITextCursor cursor;
242
243
244        while (keys.hasNext()) {
245            key = keys.next();
246            try {
247                for (int i = 0; i < placehrepr.length; i++) {
248                    String placeholderDisplayText = placehrepr[i];
249//                    Log.Debug(this, "Check placeholder key: " + placeholderDisplayText);
250                    if (placeholderDisplayText.equalsIgnoreCase(key) || placeholderDisplayText.equalsIgnoreCase("<" + key + ">")
251                            || placeholderDisplayText.equalsIgnoreCase("<RTF." + key + ">")) {
252                        Log.Debug(this, "Found placeholder key: " + key + " [" + data.get(key) + "]");
253                        if (placeholderDisplayText.startsWith("<RTF.") || placeholderDisplayText.startsWith("<rtf.")) {
254                            is = new StringInputStream(((String) data.get(key)).replace("`",
255                                    "'"));
256                            cursor = placeholders[i].getTextDocument().
257                                    getViewCursorService().
258                                    getViewCursor().
259                                    getTextCursorFromStart();
260                            cursor.gotoRange(placeholders[i].getTextRange(),
261                                    false);
262                            cursor.insertDocument(is,
263                                    RTFFilter.FILTER);
264//                            placeholders[i].getTextRange().
265//                                    setText("");
266                        } else {
267                            placeholders[i].getTextRange().setText(String.valueOf(data.get(key)));
268                        }
269                    }
270                }
271            } catch (java.lang.Exception ex) {
272                Log.Debug(ex);
273            }
274        }
275        if (!GlobalSettings.getBooleanProperty("org.openyabs.exportproperty.blankunusedfields.disable")) {
276            for (int i = 0; i < fields.size(); i++) {
277                try {
278                    ITextField xTextComponent = fields.get(i);
279                    if (xTextComponent.getXTextContent().getAnchor() != null) {
280                        if (Log.isDebugging()) {
281                            Log.Debug(this, "Filling unspecified field: " + xTextComponent.getDisplayText());
282                        }
283                        xTextComponent.getTextRange().setText("");
284                    }
285                } catch (Throwable ex) {
286                    Log.Debug(this, ex.getLocalizedMessage());
287                }
288            }
289        }
290    }
291
292    /**
293     * Fill the Variable Text Fields of the template with values
294     * @param data
295     * @throws Exception
296     * @throws NOAException
297     * @deprecated  slow :_/
298     */
299    public synchronized void fillTextVariableFields(HashMap<String, Object> data) throws Exception, NOAException {
300        Log.Debug(this, "Looking for variable fields in: " + document);
301        Iterator<String> keys = data.keySet().iterator();
302        String key = null;
303        IVariableTextFieldMaster x;
304
305        while (keys.hasNext()) {
306            // get column name
307            key = keys.next();
308            if (textFieldService == null) {
309                textFieldService = ((ITextDocument) document).getTextFieldService();
310            }
311            x = textFieldService.getVariableTextFieldMaster(key);
312
313            if (x != null) {
314                ITextField[] variables = x.getVariableTextFields();
315                for (int i = 0; i < variables.length; i++) {
316                    XPropertySet xPropertySetField = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, variables[i].getXTextContent());
317                    if (xPropertySetField.getPropertyValue("CurrentPresentation").toString().equalsIgnoreCase(key)) {
318                        Log.Debug(this, "Found variable key: " + key + " [" + data.get(key) + "]");
319                        xPropertySetField.setPropertyValue("Content", data.get(key));
320                    }
321                }
322            }
323        }
324    }
325
326    /**
327     * Export a file to another format/file. Supported target formats:
328     * <li>pdf (pdf/a)
329     * <li>odt
330     * <li>txt
331     * @param source The file to export
332     * @param target The target file
333     * @return The target file
334     * @throws DocumentException
335     */
336    public File export(File source, File target) throws DocumentException {
337        if (target.getName().split("\\.").length < 2) {
338            throw new UnsupportedOperationException("The file must have an extension: " + target);
339        }
340
341        IFilter filter = null;
342        String extension = target.getName().substring(target.getName().lastIndexOf("."), target.getName().length());
343        if (extension.equalsIgnoreCase(".pdf")) {
344            if (User.getCurrentUser().getProperties().hasProperty("pdftype")
345                    && User.getCurrentUser().getProperties().getProperty("pdftype").equalsIgnoreCase("pdf/a")) {
346                try {
347                    return exportPDFA(source, target);
348                } catch (Exception ex) {
349                    Log.Debug(ex);
350                }
351            } else {
352                filter = PDFFilter.FILTER;
353            }
354        } else if (extension.equalsIgnoreCase(".doc")) {
355            filter = MSOffice97Filter.FILTER;
356        } else if (extension.equalsIgnoreCase(".txt")) {
357            filter = TextFilter.FILTER;
358        } else if (extension.equalsIgnoreCase(".odt")) {
359            filter = OpenDocumentFilter.FILTER;
360        } else if (extension.equalsIgnoreCase(".html")) {
361            filter = HTMLFilter.FILTER;
362        }
363
364        if (filter != null) {
365            connection.getDocumentService().loadDocument(source.getAbsolutePath()).getPersistenceService().export(target.getPath(), filter);
366        } else {
367            throw new UnsupportedOperationException("File extension not supported: " + extension);
368        }
369
370        return target;
371    }
372
373    private File exportPDFA(File source, File target) throws DocumentException, MalformedURLException, FileNotFoundException, IOException, UnknownHostException {
374
375        IDocument doc = connection.getDocumentService().loadDocument(new FileInputStream(source), descriptor);
376
377        PDFFilter pdfFilter = (PDFFilter) PDFFilter.FILTER;
378        /*PDFFilterProperties pdfFilterProperties = pdfFilter.getPDFFilterProperties();
379        pdfFilterProperties.setPdfVersion(1);
380        doc.getPersistenceService().export(url, pdfFilter);*/
381
382        PropertyValue[] filterData = new PropertyValue[1];
383        filterData[0] = new PropertyValue();
384        filterData[0].Name = "SelectPdfVersion";
385        filterData[0].Value = new Integer(1); //0: normal 1.4, 1: PDF/A
386
387        String filterDefinition = pdfFilter.getFilterDefinition(doc);
388        PropertyValue[] properties = new PropertyValue[2];
389        properties[0] = new PropertyValue();
390        properties[0].Name = "FilterName"; //$NON-NLS-1$
391        properties[0].Value = filterDefinition;
392        properties[1] = new PropertyValue();
393        properties[1].Name = "FilterData";
394        properties[1].Value = filterData;
395
396
397        String url = URLAdapter.adaptURL(target.getPath());
398
399        XStorable xStorable = (XStorable) UnoRuntime.queryInterface(XStorable.class,
400                doc.getXComponent());
401        xStorable.storeToURL(url, properties);
402
403        return target;
404    }
405
406    /**
407     * Print the document directly
408     */
409    public void print() {
410        try {
411            document.getPrintService().print();
412        } catch (DocumentException ex) {
413            Log.Debug(ex);
414        }
415    }
416
417    /**
418     * Fill the tables in the document
419     * @param data
420     */
421    public synchronized void fillTables(HashMap<String, Object> data) {
422        fillTables(data, null);
423    }
424
425    /**
426     * Fills the tables in an .odt file
427     * @param data
428     * @param template
429     */
430    public void fillTables(HashMap<String, Object> data, Template template) {
431        HashMap<String, TableModel> models = template.getTables();
432
433        Log.Debug(this, "Looking for tables in: " + document);
434
435        try {
436            for (Iterator<String> it = models.keySet().iterator(); it.hasNext();) {
437                String key = it.next();
438                TableModel m = models.get(key);
439                Log.Debug(this, "Table: " + key);
440                if (tablehandler == null) {
441                    if (key.contains(".")) {
442                        key = key.substring(key.lastIndexOf(".") + 1);
443                    }
444                    Log.Debug(this, "Table identifier: " + key);
445                    tablehandler = new TableHandler((ITextDocument) document, key);
446                }
447                for (int j = 0; j < m.getRowCount(); j++) {
448                    String[] strings = new String[m.getColumnCount()];
449                    for (int k = 0; k < strings.length; k++) {
450                        if (m.getValueAt(j, k) != null) {
451                            strings[k] = String.valueOf(m.getValueAt(j, k));
452                        }
453                    }
454                    doRow(template, strings, j);
455                }
456            }
457        } catch (Exception e) {
458            Log.Debug(e);
459        }
460
461        try {
462            for (Iterator<String> it = data.keySet().iterator(); it.hasNext();) {
463                String key = it.next();
464                if (key.contains(TableHandler.KEY_TABLE)) {//Table found
465                    Log.Debug(this, "Table: " + key);
466                    @SuppressWarnings("unchecked")
467                    List<String[]> value = (List<String[]>) data.get(key);
468                    if (tablehandler == null) {
469                        if (key.contains(".")) {
470                            key = key.substring(key.lastIndexOf(".") + 1);
471                        }
472                        Log.Debug(this, "Table identifier: " + key);
473                        tablehandler = new TableHandler((ITextDocument) document, key);
474                    }
475                    for (int i = 0; i < value.size(); i++) {
476                        String[] strings = value.get(i);
477                        doRow(template, strings, i);
478                    }
479                }
480            }
481        } catch (Exception textException) {
482            Log.Debug(this, textException);
483        }
484
485
486    }
487    public static final String linkstartidentifier = "[url]";
488    public static final String linkendidentifier = "[/url]";
489
490    /**
491     * Reset the doc
492     * @throws DocumentException
493     */
494    public void clear() throws DocumentException {
495        try {
496            Log.Debug(this, "Trying to load: " + URLAdapter.adaptURL(file.getPath()));
497//            document = connection.getDocumentService().loadDocument(file.getPath().replace("\\", "/"), descriptor);
498            document = connection.getDocumentService().loadDocument(new FileInputStream(file), descriptor);
499        } catch (Exception ex) {
500            Log.Debug(ex);
501        }
502        textFieldService = null;
503        placeholders = null;
504        tablehandler = null;
505    }
506
507    /**
508     * Set the images
509     * @param data
510     */
511    public void setImages(HashMap<String, Object> data) {
512//        XTextGraphicObjectsSupplier graphicObjSupplier = (XTextGraphicObjectsSupplier) UnoRuntime.queryInterface(XTextGraphicObjectsSupplier.class,
513//      document.getXTextDocument());
514//  XNameAccess nameAccess = graphicObjSupplier.getGraphicObjects();
515//  String[] names = nameAccess.getElementNames();
516//  for (int i = 0; i < names.length; i++) {
517//            try {
518//                Any xImageAny = (Any) nameAccess.getByName(names[i]);
519//                Object xImageObject = xImageAny.getObject();
520//                XTextContent xImage = (XTextContent) xImageObject;
521//                XServiceInfo xInfo = (XServiceInfo) UnoRuntime.queryInterface(XServiceInfo.class, xImage);
522//                if (xInfo.supportsService("com.sun.star.text.TextGraphicObject")) {
523//                            try {
524//                                XPropertySet xPropSet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class,
525//                                    xImage);
526//                                String name = xPropSet.getPropertyValue("LinkDisplayName").toString();
527//                                String graphicURL = xPropSet.getPropertyValue("GraphicURL").toString();
528//                                //only ones that are not embedded
529//                                if (graphicURL.indexOf("vnd.sun.") == -1) {
530//                                  XMultiServiceFactory multiServiceFactory = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class,
531//                                      textDocument.getXTextDocument());
532//                                  XNameContainer xBitmapContainer = (XNameContainer) UnoRuntime.queryInterface(XNameContainer.class,
533//                                      multiServiceFactory.createInstance("com.sun.star.drawing.BitmapTable"));
534//                                  if (!xBitmapContainer.hasByName(name)) {
535//                                    xBitmapContainer.insertByName(name, graphicURL);
536//                                    String newGraphicURL = xBitmapContainer.getByName(name).toString();
537//                                    xPropSet.setPropertyValue("GraphicURL", newGraphicURL);
538//                                  }
539//                                }
540//                            } catch (UnknownPropertyException ex) {
541//                                Logger.getLogger(DocumentHandler.class.getName()).log(Level.SEVERE, null, ex);
542//                            } catch (WrappedTargetException ex) {
543//                                Logger.getLogger(DocumentHandler.class.getName()).log(Level.SEVERE, null, ex);
544//                            }
545//                }
546//            } catch (NoSuchElementException ex) {
547//                Logger.getLogger(DocumentHandler.class.getName()).log(Level.SEVERE, null, ex);
548//            } catch (WrappedTargetException ex) {
549//                Logger.getLogger(DocumentHandler.class.getName()).log(Level.SEVERE, null, ex);
550//            }
551//  }
552    }
553
554    private String[] refactorRow(Template template, String[] possibleCols) {
555        String format = template.__getFormat();
556        int[] intcols;
557        try {
558            String[] cols = format.split(",");
559            intcols = new int[cols.length];
560            for (int i = 0; i < intcols.length; i++) {
561                String string = cols[i];
562                intcols[i] = Integer.valueOf(string).intValue();
563            }
564        } catch (Exception ex) {
565            Log.Debug(this, "An error occured, using default format now. " + ex.getMessage());
566            intcols = new int[possibleCols.length];
567            for (int i = 0; i < intcols.length; i++) {
568                intcols[i] = i + 1;
569            }
570        }
571        String[] form = new String[intcols.length];
572        for (int i = 0; i < intcols.length; i++) {
573            try {
574                form[i] = possibleCols[intcols[i] - 1];
575            } catch (Exception e) {
576                // Log.Debug(this, "Too much columns in the format definition: " + e);
577            }
578        }
579
580        return form;
581    }
582
583    private void doRow(Template template, String[] strings, int row) {
584        if (template != null) {
585            strings = refactorRow(template, strings);
586        }
587        if (Log.getLoglevel() == Log.LOGLEVEL_DEBUG) {
588            Log.Debug(this, Arrays.asList(strings).toString());
589        }
590        for (int j = 0; j < strings.length; j++) {
591            String cellValue = strings[j];
592            if (cellValue == null) {
593                cellValue = "";
594            }
595            cellValue = cellValue.replaceAll("\\<.*?\\>", "");//remove html/xml tags
596            if (!cellValue.contains("://")) {//lets say its a valid url
597                try {
598                    tablehandler.setValueAt(cellValue, j, row);
599                } catch (TextException ex) {
600                    Log.Debug(ex);
601                }
602            } else {
603                try {
604                    String linkname = "Link";
605                    if (cellValue.contains("@")) {
606                        String link1 = cellValue.split("@")[1];
607                        linkname = cellValue.split("@")[0];
608                        cellValue = link1;
609                    }
610                    tablehandler.setHyperlinkAt(linkname, cellValue, j, row);
611                } catch (Exception ex) {
612                    Log.Debug(ex);
613                }
614            }
615        }
616    }
617}