Statistics
| Revision:

svn-document-layout / trunk / org.gvsig.app.document.layout2.app / org.gvsig.app.document.layout2.app.mainplugin / src / main / java / org / gvsig / app / project / documents / layout / report / LayoutReportActionImpl.java @ 1615

History | View | Annotate | Download (22.8 KB)

1
package org.gvsig.app.project.documents.layout.report;
2

    
3
import java.awt.Color;
4
import java.awt.Dimension;
5
import java.awt.event.ActionEvent;
6
import java.awt.geom.Point2D;
7
import java.io.File;
8
import java.io.InputStream;
9
import java.util.ArrayList;
10
import java.util.List;
11
import java.util.Objects;
12
import javax.json.JsonObject;
13
import javax.swing.JComponent;
14
import javax.swing.JOptionPane;
15
import javax.swing.SwingUtilities;
16
import org.apache.commons.io.IOUtils;
17
import org.apache.commons.lang3.StringUtils;
18
import org.cresques.cts.ICoordTrans;
19
import org.gvsig.andami.ui.mdiManager.IWindow;
20
import org.gvsig.app.ApplicationLocator;
21
import org.gvsig.app.ApplicationManager;
22
import org.gvsig.app.project.documents.Document;
23
import org.gvsig.app.project.documents.layout.LayoutContext;
24
import org.gvsig.app.project.documents.layout.fframes.FFrameView;
25
import org.gvsig.app.project.documents.layout.fframes.IFFrame;
26
import org.gvsig.app.project.documents.layout.gui.LayoutPanel;
27
import static org.gvsig.app.project.documents.layout.report.LayoutReportActionFactory.LAYOUT_REPORT_ACTION_NAME;
28
import org.gvsig.app.project.documents.view.ViewDocument;
29
import org.gvsig.app.project.documents.view.gui.IView;
30
import org.gvsig.desktopopen.DesktopOpen;
31
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
32
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
33
import org.gvsig.expressionevaluator.ExpressionUtils;
34
import org.gvsig.expressionevaluator.MutableSymbolTable;
35
import org.gvsig.fmap.dal.DALLocator;
36
import org.gvsig.fmap.dal.exception.DataException;
37
import org.gvsig.fmap.dal.expressionevaluator.FeatureSymbolTable;
38
import org.gvsig.fmap.dal.feature.Feature;
39
import org.gvsig.fmap.dal.feature.FeatureQuery;
40
import org.gvsig.fmap.dal.feature.FeatureSelection;
41
import org.gvsig.fmap.dal.feature.FeatureSet;
42
import org.gvsig.fmap.dal.feature.FeatureStore;
43
import org.gvsig.fmap.dal.swing.DALSwingLocator;
44
import org.gvsig.fmap.dal.swing.DataSwingManager;
45
import org.gvsig.fmap.dal.swing.report.AbstractReportAction;
46
import org.gvsig.fmap.dal.swing.report.ReportActionFactory;
47
import org.gvsig.fmap.geom.Geometry;
48
import org.gvsig.fmap.geom.GeometryLocator;
49
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
50
import org.gvsig.fmap.geom.primitive.Envelope;
51
import org.gvsig.fmap.mapcontext.MapContext;
52
import org.gvsig.fmap.mapcontext.ViewPort;
53
import org.gvsig.fmap.mapcontext.layers.FLayer;
54
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
55
import org.gvsig.fmap.mapcontext.layers.vectorial.GraphicLayer;
56
import org.gvsig.pdf.lib.api.PDFDocument;
57
import org.gvsig.pdf.lib.api.PDFLocator;
58
import org.gvsig.pdf.lib.api.PDFManager;
59
import org.gvsig.pdf.swing.api.PDFSwingLocator;
60
import org.gvsig.pdf.swing.api.PDFSwingManager;
61
import org.gvsig.pdf.swing.api.PDFViewer;
62
import org.gvsig.symbology.SymbologyLocator;
63
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.ISimpleTextSymbol;
64
import org.gvsig.tools.ToolsLocator;
65
import org.gvsig.tools.dispose.DisposeUtils;
66
import org.gvsig.tools.exception.BaseException;
67
import org.gvsig.tools.i18n.I18nManager;
68
import org.gvsig.tools.locator.LocatorException;
69
import org.gvsig.tools.persistence.PersistenceManager;
70
import org.gvsig.tools.persistence.PersistentState;
71
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
72
import org.gvsig.tools.swing.api.ToolsSwingLocator;
73
import org.gvsig.tools.swing.api.ToolsSwingUtils;
74
import org.gvsig.tools.swing.api.task.JTaskStatus;
75
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
76
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
77
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
78
import org.gvsig.tools.task.SimpleTaskStatus;
79
import org.gvsig.tools.util.ToolsUtilLocator;
80

    
81
/**
82
 *
83
 * @author jjdelcerro
84
 */
85
@SuppressWarnings("UseSpecificCatch")
86
public class LayoutReportActionImpl extends AbstractReportAction implements LayoutReportAction {
87

    
88
    public static LayoutReportActionImpl createFakeLayoutReportAction(Document doc) {
89
        ApplicationManager application = ApplicationLocator.getApplicationManager();
90
        DataSwingManager dataSwingManager = DALSwingLocator.getDataSwingManager();
91
        Feature f = null;
92
        FeatureStore theStore = null;
93
        ReportActionFactory theFactory = dataSwingManager.getReportActionFactory(LAYOUT_REPORT_ACTION_NAME);
94
        try {
95
            IWindow activeView = application.getActiveWindow(ViewDocument.class);
96
            ViewDocument viewdoc = (ViewDocument) ((IView)activeView).getDocument();
97
            FLyrVect layer = viewdoc.getMapContext().getLayers().getFirstActiveVectorLayer();
98
            theStore = layer.getFeatureStore();
99
            if( theStore.isFeatureSelectionEmpty() ) {
100
                f = theStore.first();
101
            } else {
102
                f = theStore.getFeatureSelection().first();
103
            }
104
        } catch(Throwable t) {
105
            LOGGER.debug("Can't retrieve test feature",t);
106
        }
107
        LayoutReportActionImpl report = new LayoutReportActionImpl(theFactory, theStore, f);
108
        report.getSymbolTable().setVar("$LAYOUT", doc);
109
        report.getSymbolTable().setVar("$PAGE", 1);
110
        report.getSymbolTable().setVar("$PAGES", 1);
111
        return report;        
112
    }
113
    
114
    
115
    private final FeatureStore store;
116
    private FeatureQuery query;
117
    private FeatureSet selection;
118
    private Feature current_row;
119
    private MutableSymbolTable symbolTable;
120
    private FeatureSymbolTable fSymbolTable;
121
    private Iterable<Feature> set;
122
    private int featuresCount;
123
    private LayoutReportActionParameters parameters;
124
    
125
    @SuppressWarnings("OverridableMethodCallInConstructor")
126
    private LayoutReportActionImpl(ReportActionFactory factory, FeatureStore store, JsonObject json) {
127
        super(factory, null);
128
        this.store = store;
129
        this.selection = null;
130
        this.query = null;
131
        this.current_row = null;
132
        
133
        this.parameters = LayoutReportActionParameters.create();
134
        this.parameters.fromJson(json);
135
        
136
        this.setReportName(this.parameters.getIdentifier());
137
        this.setReportLabel(this.parameters.getLabel());
138
    }
139
    
140
    @SuppressWarnings("OverridableMethodCallInConstructor")
141
    private LayoutReportActionImpl(ReportActionFactory factory, FeatureStore store, Feature feature) {
142
        // Fake layoutReportAction constructor
143
        this(
144
                factory, 
145
                store, 
146
                LayoutReportActionParameters.create(store.getName()).toJson()
147
        );
148
        try {
149
            this.selection = store.createFeatureSelection();
150
            ((FeatureSelection)this.selection).select(feature);
151
        } catch(Throwable t) {
152
            LOGGER.debug("Can't initialize selection",t);
153
        }
154
        this.query = store.createFeatureQuery(feature.createFilter());
155
        this.current_row = feature;
156

    
157
    }
158
    
159
    @SuppressWarnings("OverridableMethodCallInConstructor")
160
    public LayoutReportActionImpl(ReportActionFactory factory, FeatureStore store, FeatureQuery query, FeatureSet selection, final JsonObject json) {
161
        this(factory, store, json);
162
        
163
        this.selection = selection;
164
        this.query = query;
165
    }
166

    
167
    public Feature row() {
168
        return this.current_row;
169
    }
170
    
171
    private Iterable<Feature> features() {
172
        if( this.set == null ) {
173
                if(this.selection == null){
174
                try {
175
                    FeatureSet fset = store.getFeatureSet(query);
176
                    this.featuresCount = fset.size();
177
                    this.set = fset;
178
                } catch (DataException ex) {
179
                    throw new RuntimeException("Can't create dynamic-text report.", ex);
180
                }
181
            } else {
182
                this.featuresCount = this.selection.size();
183
                if(this.selection instanceof FeatureSelection){
184
                    this.set = this.store.getFeaturesIterable(((FeatureSelection)this.selection).referenceIterator());
185
                } else {
186
                    this.set = this.selection;
187
                    DisposeUtils.bind(this.set);
188
                }
189
            }
190
        }
191
        return this.set;
192
    }
193
    
194
    
195
    @Override
196
    public void actionPerformed(ActionEvent e) {
197
        if (!this.isEnabled()) {
198
            return;
199
        }
200
        I18nManager i18n = ToolsLocator.getI18nManager();
201
        final WindowManager_v2 windowManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
202
        final JTaskStatus taskStatusPanel = ToolsSwingLocator.getTaskStatusSwingManager().createJTaskStatus();
203
        final LayoutReportAction report = this;
204

    
205
        SimpleTaskStatus theStatus = this.getStatus();
206
        theStatus.setIndeterminate();
207
        taskStatusPanel.setShowRemoveTaskButton(false);
208
        taskStatusPanel.bind(theStatus);
209
        ToolsSwingUtils.ensureRowsCols(taskStatusPanel, 4, 100, 5, 200);
210

    
211
        windowManager.showWindow(
212
                taskStatusPanel.asJComponent(),
213
                i18n.getTranslation("_Creating_report")+" '" + this.getReportLabel() + "'...",
214
                WindowManager.MODE.TOOL
215
        );
216

    
217
        Thread task = new Thread(() -> {
218
            List<File> singlePdfFiles = new ArrayList();
219
            Iterable<Feature> features = null; 
220
            try {
221
                String title = this.getReportLabel();
222
                String creator = "gvSIG-desktop";
223
                String subject = "Layout report";
224

    
225
                File pdfFile = ToolsLocator.getFoldersManager().getUniqueTemporaryFile("report.pdf");
226
                        int pag = 0;
227
                        features = features();
228
                        theStatus.setRangeOfValues(1, featuresCount);
229
                        theStatus.message(i18n.getTranslation("_Building_pages"));
230
                        for (Feature feature : features) {
231
                            if( theStatus.isCancellationRequested() ) {
232
                                theStatus.cancel();
233
                                return;
234
                            }
235
                            File f = printReport(feature, ++pag);
236
                            singlePdfFiles.add(f);
237
                            theStatus.incrementCurrentValue();
238
                        }
239

    
240
                        theStatus.message(i18n.getTranslation("_Building_pdf"));
241
                        PDFManager pdfManager = PDFLocator.getPDFManager();
242
                        pdfManager.merge(singlePdfFiles, pdfFile, title, creator, subject, theStatus);
243

    
244
                        if (this.parameters.isUseInternalPdfViewer()) {
245
                            this.showEmbedded(pdfFile);
246
                        } else {
247
                            this.showExternal(pdfFile);
248
                        }
249

    
250
                        theStatus.terminate();
251
                        SwingUtilities.invokeLater(() -> {
252
                            taskStatusPanel.setVisible(false);
253
                        });
254
                
255
            } catch (Throwable t) {
256
                LOGGER.warn("Can't create layout report.", t);
257
                theStatus.abort();
258
            } finally {
259
                for (File singlePdfFile : singlePdfFiles) {
260
                    singlePdfFile.delete();
261
                }
262
                DisposeUtils.disposeQuietly(features);
263

    
264
            }
265
        }, "Report_" + report.getReportName());
266
        task.start();
267
        
268
    }
269
    
270
    private File printReport(Feature feature, int page) throws Exception {
271
        this.current_row = feature;
272
        final LayoutPanel layout = this.getTemplateAsLayout();
273
        final LayoutContext context = layout.getLayoutContext();
274
        final Document document = layout.getDocument();
275

    
276
        this.getSymbolTable();
277
        fSymbolTable.setFeature(current_row);
278
        this.symbolTable.setVar("$LAYOUT", document);
279
        this.symbolTable.setVar("$PAGE", page);
280
        this.symbolTable.setVar("$PAGES", this.featuresCount);
281

    
282
        File pdfFile = null;
283
        Object previous_report = document.getProperty("$REPORT");
284
        I18nManager i18n = ToolsLocator.getI18nManager();
285
        try {
286
            document.setProperty("$REPORT", this);
287
            /*
288
                TODO: Aqui podriamos consultar en el json para ver si hacemos:
289
                x zoom al envelope de la geometria de current_row, 
290
                x si le aplicamos un buffer antes a ese envelop, 
291
                X si la seleccionamos... 
292
                - asi como con que vista tenemos que hacerlo. ????
293
             */
294
            int count = 1;
295
            MapContext mapContext = null;
296
            MapContext mapContextCandidate = null;
297
            for (IFFrame frame : context.getAllFFrames()) {
298
                if (frame instanceof FFrameView) {
299
                    if (mapContextCandidate == null) {
300
                        mapContextCandidate = ((FFrameView) frame).getMapContext();
301
                    }
302
                    String frameTag = frame.getTag();
303
                    String countTag = "#" + count;
304
                    if (StringUtils.equalsIgnoreCase(this.parameters.getViewTag(), frameTag)
305
                            || StringUtils.equalsIgnoreCase(this.parameters.getViewTag(), countTag)) {
306
                        mapContext = ((FFrameView) frame).getMapContext();
307
                        break;
308
                    }
309
                }
310
            }
311
            if (mapContext == null) {
312
                mapContext = mapContextCandidate;
313
            };
314

    
315
            if (mapContext != null) {
316
                mapContext.setPrintGraphicsLayer(this.parameters.isHighlightRecord());
317
                ICoordTrans ct = null;
318
                for (FLayer layer : mapContext.getLayers().getLayers(null)) {
319
                    if (layer instanceof FLyrVect) {
320
                        FeatureStore layerStore = ((FLyrVect) layer).getFeatureStore();
321
                        if (layerStore != null) {
322
                            if (layerStore.getParameters().isTheSameStore(this.store.getParameters())) {
323
                                ct = ((FLyrVect) layer).getCoordTrans();
324
                                break;
325
                            }
326
                        }
327
                    }
328
                }
329
                Geometry geom = this.current_row.getDefaultGeometry();
330
                if (geom != null) {
331
                    geom = geom.cloneGeometry();
332
                    if (ct != null && ct.getPOrig().equals(geom.getProjection())) {
333
                        geom.reProject(ct);
334
                    } else if (!geom.getProjection().equals(mapContext.getProjection())) {
335
                        ct = geom.getProjection().getCT(mapContext.getProjection());
336
                        geom.reProject(ct);
337
                    }
338
                    if (this.parameters.isZoomToCurrentRow()) {
339

    
340
                        Envelope envelope = geom
341
                                .getEnvelope().getGeometry().buffer(this.parameters.getBufferSize()).getEnvelope();
342
                        mapContext.getViewPort().setEnvelope(envelope);
343

    
344
                    } else if (this.parameters.isCenterToCurrentRow()) {
345

    
346
                        Envelope envelope = geom
347
                                .getEnvelope().getGeometry().buffer(this.parameters.getBufferSize()).getEnvelope();
348
                        center(mapContext, envelope);
349

    
350
                    } else {
351
                        //DO NOTHING ??
352
                    }
353
                    if(this.parameters.isHighlightRecord()){
354
                        GraphicLayer graphicsLayer = mapContext.getGraphicsLayer();
355
                        graphicsLayer.clear();
356
                        int idSymbol = graphicsLayer.addSymbol(this.parameters.getHighlightSymbol(this.store));
357
                        if(this.parameters.isApplySymbolToRecord()){
358
                            //Do nothing, is the default behavior
359
                        }
360
                        if(this.parameters.isApplySymbolToEverythingExceptRecord()){
361
                            Geometry viewPortGeom = mapContext.getViewPort().getAdjustedEnvelope().getGeometry();
362
                            if(geom.isValid()) {
363
                                geom = viewPortGeom.difference(geom);
364
                            } else {
365
                                Geometry geom2 = geom.fix();
366
                                if(geom2 != null){
367
                                    geom = viewPortGeom.difference(geom2);
368
                                } else {
369
                                    geom = viewPortGeom;
370
                                    ISimpleTextSymbol textSymbol = SymbologyLocator.getSymbologyManager().createSimpleTextSymbol();
371
                                    textSymbol.setTextColor(Color.RED.darker());
372
                                    textSymbol.setHaloColor(Color.WHITE);
373
                                    textSymbol.setDrawWithHalo(true);
374
                                    
375
                                    int idPointSymbol = graphicsLayer.addSymbol(textSymbol);
376
                                    graphicsLayer.addGraphic("LayourReport", geom.centroid(), idPointSymbol, i18n.getTranslation("_Invalid_geometry"));
377
                                }
378
                            }
379
                        }
380
                        graphicsLayer.addGraphic("LayourReport", geom, idSymbol);
381
                    }
382
                }
383
            }
384

    
385
            context.fullRefresh();
386
            layout.getLayoutControl().getLayoutDraw().initialize();
387

    
388
            pdfFile = ToolsLocator.getFoldersManager().getUniqueTemporaryFile("report.pdf");
389
            layout.layoutToPDF(pdfFile);
390
        } catch (Throwable th) {
391
            LOGGER.warn("Can't print report.", th);
392
            this.getStatus().message(i18n.getTranslation("_Cant_print_report")+"\n\n"+th.getMessage());
393
            throw th;
394
        } finally {
395
            document.setProperty("$REPORT", previous_report);
396
        }
397

    
398
        return pdfFile;
399
    }
400

    
401
    private void center(MapContext mapContext, Envelope envelope) throws LocatorException, CreateEnvelopeException {
402
        ViewPort viewPort = mapContext.getViewPort();
403
        Envelope oldExtent = viewPort.getAdjustedEnvelope();
404
        double oldCenterX = oldExtent.getCenter(0);
405
        double oldCenterY = oldExtent.getCenter(1);
406
        double centerX = envelope.getCenter(0);
407
        double centerY = envelope.getCenter(1);
408
        Point2D.Double center = new Point2D.Double(centerX, centerY);
409
        double movX = centerX - oldCenterX;
410
        double movY = centerY - oldCenterY;
411
        
412
        double minx = oldExtent.getMinimum(0) + movX;
413
        double miny = oldExtent.getMinimum(1) + movY;
414
        double maxX = oldExtent.getMaximum(0) + movX;
415
        double maxY = oldExtent.getMaximum(1) + movY;
416
        Envelope extent = GeometryLocator.getGeometryManager().createEnvelope(
417
                minx, miny,
418
                maxX, maxY,
419
                Geometry.SUBTYPES.GEOM2D);
420
        viewPort.setEnvelope(extent);
421
    }
422

    
423
    private void showEmbedded(File pdfFile) {
424
        if (!SwingUtilities.isEventDispatchThread()) {
425
            SwingUtilities.invokeLater(() -> {
426
                showEmbedded(pdfFile);
427
            });
428
            return;
429
        }
430
        try {
431
            final WindowManager windowManager = ToolsSwingLocator.getWindowManager();
432
            final PDFSwingManager pdfSwingManager = PDFSwingLocator.getPDFSwingManager();
433
            final PDFManager pdfManager = PDFLocator.getPDFManager();
434
            
435
            final PDFDocument pdfdoc = pdfManager.createPDFDocument(pdfFile);
436
            PDFViewer viewer = pdfSwingManager.createPDFViewer();
437
            viewer.put(pdfdoc);
438
            viewer.setMode(PDFViewer.MODE_LIGHT);
439
            
440
            JComponent comp = viewer.asJComponent();
441
            Dimension size = ToolsSwingUtils.ensureRowsCols(comp.getPreferredSize(), 20, 100, 40, 150);
442
            comp.setSize(size);
443
            
444
            String title = "Report: " + this.getLabel();
445
            windowManager.showWindow(
446
                    comp,
447
                    title,
448
                    WindowManager.MODE.WINDOW
449
            );
450
        } catch (Exception ex) {
451
            LOGGER.warn("Can't show pdf file '" + Objects.toString(pdfFile) + "'", ex);
452
            I18nManager i18n = ToolsLocator.getI18nManager();
453
            ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
454
            dialogs.messageDialog(
455
                    i18n.getTranslation("_Cant_show_pdf_file")+" (" + Objects.toString(pdfFile) + ")\n\n"+BaseException.getMessageStack(ex, 0),
456
                    "Creating report '" + this.getReportLabel() + "'",
457
                    JOptionPane.WARNING_MESSAGE
458
            );
459
        }
460
    }
461

    
462
    private void showExternal(File pdfFile) {
463
        if (!SwingUtilities.isEventDispatchThread()) {
464
            SwingUtilities.invokeLater(() -> {
465
                showExternal(pdfFile);
466
            });
467
            return;
468
        }
469
        DesktopOpen desktop = ToolsUtilLocator.getToolsUtilManager().createDesktopOpen();
470
        desktop.open(pdfFile);
471
    }
472
    
473
    private LayoutPanel getTemplateAsLayout() throws Exception {
474
        ResourcesStorage.Resource resource = getTemplateAsResource();
475
        if(resource == null){
476
            return null;
477
        }
478
        InputStream is = null;
479
        try {
480
            is = resource.asInputStream();
481
            PersistenceManager persistenceManager = ToolsLocator.getPersistenceManager();
482
            PersistentState persistentState = persistenceManager.loadState(is);
483

    
484
            LayoutPanel layout = (LayoutPanel) persistenceManager.create(persistentState);
485

    
486
            return layout;
487
        } finally {
488
            IOUtils.closeQuietly(is);
489
        }
490
    }
491
    
492
    @Override
493
    public ResourcesStorage.Resource getTemplateAsResource() {
494
        ResourcesStorage resources = store.getResourcesStorage();
495
        if (resources == null) {
496
            return null;
497
        }
498
        String templateName = this.parameters.getTemplateName(); //.getString(LAYOUT_REPORT_TEMPLATE_NAME, LAYOUT_REPORT_DEFAULT_TEMPLATE_NAME); // "1.layout"...
499
        ResourcesStorage.Resource resource = resources.getResource(templateName);
500
        return resource;
501
    }
502
    
503
    public MutableSymbolTable getSymbolTable() {
504
        if( this.symbolTable == null ) {
505
            this.symbolTable = ExpressionUtils.createSymbolTable();
506
            fSymbolTable = DALLocator.getDataManager().createFeatureSymbolTable();
507
            fSymbolTable.setFeature(current_row);
508
            this.symbolTable.addSymbolTable(fSymbolTable);
509
            this.symbolTable.setVar("$REPORT", this);
510
        }
511
        return this.symbolTable;
512
    }
513

    
514
    @Override
515
    public String evaluateDynamicText(String s) {
516
        ExpressionEvaluatorManager manager = ExpressionEvaluatorLocator.getExpressionEvaluatorManager();
517
        if( !manager.isDynamicText(s) ) {
518
            return s;
519
        }
520
        String x = manager.evaluateDynamicText(
521
                this.getSymbolTable(), 
522
                s, 
523
                null, 
524
                this.store.getResourcesStorage()
525
        );
526
        return x;
527
    }
528
    
529
    public LayoutReportActionParameters getParameters() {
530
        return this.parameters;
531
    }
532

    
533
}