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 @ 1608

History | View | Annotate | Download (21.4 KB)

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

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

    
78
/**
79
 *
80
 * @author jjdelcerro
81
 */
82
@SuppressWarnings("UseSpecificCatch")
83
public class LayoutReportActionImpl extends AbstractReportAction implements LayoutReportAction {
84

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

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

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

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

    
208
        windowManager.showWindow(
209
                taskStatusPanel.asJComponent(),
210
                i18n.getTranslation("_Creating_report")+" '" + this.getReportLabel() + "'...",
211
                WindowManager.MODE.TOOL
212
        );
213

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

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

    
237
                        theStatus.message(i18n.getTranslation("_Building_pdf"));
238
                        PDFManager pdfManager = PDFLocator.getPDFManager();
239
                        pdfManager.merge(singlePdfFiles, pdfFile, title, creator, subject, theStatus);
240

    
241
                        if (this.parameters.isUseInternalPdfViewer()) {
242
                            this.showEmbedded(pdfFile);
243
                        } else {
244
                            this.showExternal(pdfFile);
245
                        }
246

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

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

    
273
        this.getSymbolTable();
274
        fSymbolTable.setFeature(current_row);
275
        this.symbolTable.setVar("$LAYOUT", document);
276
        this.symbolTable.setVar("$PAGE", page);
277
        this.symbolTable.setVar("$PAGES", this.featuresCount);
278

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

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

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

    
342
                    } else if (this.parameters.isCenterToCurrentRow()) {
343

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

    
348
                    } else {
349
                        //DO NOTHING ??
350
                    }
351
                    if(this.parameters.isHighlightRecord()){
352
                        GraphicLayer graphicsLayer = mapContext.getGraphicsLayer();
353
                        graphicsLayer.clear();
354
                        int idSymbol = graphicsLayer.addSymbol(this.parameters.getHighlightSymbol(this.store));
355
                        if(this.parameters.isApplySymbolToRecord()){
356
                            //Do nothing, is the default behavior
357
                        }
358
                        if(this.parameters.isApplySymbolToEverythingExceptRecord()){
359
                            geom = mapContext.getViewPort().getAdjustedEnvelope().getGeometry().difference(geom);
360
                        }
361
                        graphicsLayer.addGraphic("", geom, idSymbol);
362
                    }
363
                }
364
            }
365

    
366
            context.fullRefresh();
367
            layout.getLayoutControl().getLayoutDraw().initialize();
368

    
369
            pdfFile = ToolsLocator.getFoldersManager().getUniqueTemporaryFile("report.pdf");
370
            layout.layoutToPDF(pdfFile);
371
        } finally {
372
            document.setProperty("$REPORT", previous_report);
373
        }
374

    
375
        return pdfFile;
376
    }
377

    
378
    private void center(MapContext mapContext, Envelope envelope) throws LocatorException, CreateEnvelopeException {
379
        ViewPort viewPort = mapContext.getViewPort();
380
        Envelope oldExtent = viewPort.getAdjustedEnvelope();
381
        double oldCenterX = oldExtent.getCenter(0);
382
        double oldCenterY = oldExtent.getCenter(1);
383
        double centerX = envelope.getCenter(0);
384
        double centerY = envelope.getCenter(1);
385
        Point2D.Double center = new Point2D.Double(centerX, centerY);
386
        double movX = centerX - oldCenterX;
387
        double movY = centerY - oldCenterY;
388
        
389
        double minx = oldExtent.getMinimum(0) + movX;
390
        double miny = oldExtent.getMinimum(1) + movY;
391
        double maxX = oldExtent.getMaximum(0) + movX;
392
        double maxY = oldExtent.getMaximum(1) + movY;
393
        Envelope extent = GeometryLocator.getGeometryManager().createEnvelope(
394
                minx, miny,
395
                maxX, maxY,
396
                Geometry.SUBTYPES.GEOM2D);
397
        viewPort.setEnvelope(extent);
398
    }
399

    
400
    private void showEmbedded(File pdfFile) {
401
        if (!SwingUtilities.isEventDispatchThread()) {
402
            SwingUtilities.invokeLater(() -> {
403
                showEmbedded(pdfFile);
404
            });
405
            return;
406
        }
407
        try {
408
            final WindowManager windowManager = ToolsSwingLocator.getWindowManager();
409
            final PDFSwingManager pdfSwingManager = PDFSwingLocator.getPDFSwingManager();
410
            final PDFManager pdfManager = PDFLocator.getPDFManager();
411
            
412
            final PDFDocument pdfdoc = pdfManager.createPDFDocument(pdfFile);
413
            PDFViewer viewer = pdfSwingManager.createPDFViewer();
414
            viewer.put(pdfdoc);
415
            viewer.setMode(PDFViewer.MODE_LIGHT);
416
            
417
            JComponent comp = viewer.asJComponent();
418
            Dimension size = ToolsSwingUtils.ensureRowsCols(comp.getPreferredSize(), 20, 100, 40, 150);
419
            comp.setSize(size);
420
            
421
            String title = "Report: " + this.getLabel();
422
            windowManager.showWindow(
423
                    comp,
424
                    title,
425
                    WindowManager.MODE.WINDOW
426
            );
427
        } catch (Exception ex) {
428
            LOGGER.warn("Can't show pdf file '" + Objects.toString(pdfFile) + "'", ex);
429
            I18nManager i18n = ToolsLocator.getI18nManager();
430
            ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
431
            dialogs.messageDialog(
432
                    i18n.getTranslation("_Cant_show_pdf_file")+" (" + Objects.toString(pdfFile) + ")\n\n"+BaseException.getMessageStack(ex, 0),
433
                    "Creating report '" + this.getReportLabel() + "'",
434
                    JOptionPane.WARNING_MESSAGE
435
            );
436
        }
437
    }
438

    
439
    private void showExternal(File pdfFile) {
440
        if (!SwingUtilities.isEventDispatchThread()) {
441
            SwingUtilities.invokeLater(() -> {
442
                showExternal(pdfFile);
443
            });
444
            return;
445
        }
446
        DesktopOpen desktop = ToolsUtilLocator.getToolsUtilManager().createDesktopOpen();
447
        desktop.open(pdfFile);
448
    }
449
    
450
    private LayoutPanel getTemplateAsLayout() throws Exception {
451
        ResourcesStorage.Resource resource = getTemplateAsResource();
452
        if(resource == null){
453
            return null;
454
        }
455
        InputStream is = null;
456
        try {
457
            is = resource.asInputStream();
458
            PersistenceManager persistenceManager = ToolsLocator.getPersistenceManager();
459
            PersistentState persistentState = persistenceManager.loadState(is);
460

    
461
            LayoutPanel layout = (LayoutPanel) persistenceManager.create(persistentState);
462

    
463
            return layout;
464
        } finally {
465
            IOUtils.closeQuietly(is);
466
        }
467
    }
468
    
469
    @Override
470
    public ResourcesStorage.Resource getTemplateAsResource() {
471
        ResourcesStorage resources = store.getResourcesStorage();
472
        if (resources == null) {
473
            return null;
474
        }
475
        String templateName = this.parameters.getTemplateName(); //.getString(LAYOUT_REPORT_TEMPLATE_NAME, LAYOUT_REPORT_DEFAULT_TEMPLATE_NAME); // "1.layout"...
476
        ResourcesStorage.Resource resource = resources.getResource(templateName);
477
        return resource;
478
    }
479
    
480
    public MutableSymbolTable getSymbolTable() {
481
        if( this.symbolTable == null ) {
482
            this.symbolTable = ExpressionUtils.createSymbolTable();
483
            fSymbolTable = DALLocator.getDataManager().createFeatureSymbolTable();
484
            fSymbolTable.setFeature(current_row);
485
            this.symbolTable.addSymbolTable(fSymbolTable);
486
            this.symbolTable.setVar("$REPORT", this);
487
        }
488
        return this.symbolTable;
489
    }
490

    
491
    @Override
492
    public String evaluateDynamicText(String s) {
493
        ExpressionEvaluatorManager manager = ExpressionEvaluatorLocator.getExpressionEvaluatorManager();
494
        if( !manager.isDynamicText(s) ) {
495
            return s;
496
        }
497
        String x = manager.evaluateDynamicText(
498
                this.getSymbolTable(), 
499
                s, 
500
                null, 
501
                this.store.getResourcesStorage()
502
        );
503
        return x;
504
    }
505
    
506
    public LayoutReportActionParameters getParameters() {
507
        return this.parameters;
508
    }
509

    
510
}