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

History | View | Annotate | Download (18.5 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.IOException;
8
import java.io.InputStream;
9
import java.util.ArrayList;
10
import java.util.List;
11
import javax.json.Json;
12
import javax.json.JsonObject;
13
import javax.swing.JComponent;
14
import org.apache.commons.io.IOUtils;
15
import org.apache.commons.lang3.StringUtils;
16
import org.gvsig.andami.ui.mdiManager.IWindow;
17
import org.gvsig.app.ApplicationLocator;
18
import org.gvsig.app.ApplicationManager;
19
import org.gvsig.app.project.documents.Document;
20
import org.gvsig.app.project.documents.layout.LayoutContext;
21
import org.gvsig.app.project.documents.layout.fframes.FFrameView;
22
import org.gvsig.app.project.documents.layout.fframes.IFFrame;
23
import org.gvsig.app.project.documents.layout.gui.LayoutPanel;
24
import static org.gvsig.app.project.documents.layout.report.LayoutReportActionFactory.LAYOUT_REPORT_ACTION_NAME;
25
import org.gvsig.app.project.documents.view.ViewDocument;
26
import org.gvsig.app.project.documents.view.gui.IView;
27
import org.gvsig.desktopopen.DesktopOpen;
28
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
29
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
30
import org.gvsig.expressionevaluator.ExpressionUtils;
31
import org.gvsig.expressionevaluator.MutableSymbolTable;
32
import org.gvsig.fmap.dal.DALLocator;
33
import org.gvsig.fmap.dal.exception.DataException;
34
import org.gvsig.fmap.dal.expressionevaluator.FeatureSymbolTable;
35
import org.gvsig.fmap.dal.feature.Feature;
36
import org.gvsig.fmap.dal.feature.FeatureQuery;
37
import org.gvsig.fmap.dal.feature.FeatureSelection;
38
import org.gvsig.fmap.dal.feature.FeatureSet;
39
import org.gvsig.fmap.dal.feature.FeatureStore;
40
import org.gvsig.fmap.dal.swing.DALSwingLocator;
41
import org.gvsig.fmap.dal.swing.DataSwingManager;
42
import org.gvsig.fmap.dal.swing.report.AbstractReportAction;
43
import org.gvsig.fmap.dal.swing.report.ReportActionFactory;
44
import org.gvsig.fmap.geom.Geometry;
45
import org.gvsig.fmap.geom.GeometryLocator;
46
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
47
import org.gvsig.fmap.geom.primitive.Envelope;
48
import org.gvsig.fmap.mapcontext.MapContext;
49
import org.gvsig.fmap.mapcontext.ViewPort;
50
import org.gvsig.fmap.mapcontext.layers.FLayer;
51
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
52
import org.gvsig.pdf.lib.api.PDFDocument;
53
import org.gvsig.pdf.lib.api.PDFLocator;
54
import org.gvsig.pdf.lib.api.PDFManager;
55
import org.gvsig.pdf.swing.api.PDFSwingLocator;
56
import org.gvsig.pdf.swing.api.PDFSwingManager;
57
import org.gvsig.pdf.swing.api.PDFViewer;
58
import org.gvsig.tools.ToolsLocator;
59
import org.gvsig.tools.locator.LocatorException;
60
import org.gvsig.tools.persistence.PersistenceManager;
61
import org.gvsig.tools.persistence.PersistentState;
62
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
63
import org.gvsig.tools.swing.api.ToolsSwingLocator;
64
import org.gvsig.tools.swing.api.ToolsSwingUtils;
65
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
66
import org.gvsig.tools.util.ToolsUtilLocator;
67

    
68
/**
69
 *
70
 * @author jjdelcerro
71
 */
72
@SuppressWarnings("UseSpecificCatch")
73
public class LayoutReportActionImpl extends AbstractReportAction implements LayoutReportAction {
74

    
75
    public static LayoutReportActionImpl createFakeLayoutReportAction(Document doc) {
76
        ApplicationManager application = ApplicationLocator.getApplicationManager();
77
        DataSwingManager dataSwingManager = DALSwingLocator.getDataSwingManager();
78
        Feature f = null;
79
        FeatureStore theStore = null;
80
        ReportActionFactory theFactory = dataSwingManager.getReportActionFactory(LAYOUT_REPORT_ACTION_NAME);
81
        try {
82
            IWindow activeView = application.getActiveWindow(ViewDocument.class);
83
            ViewDocument viewdoc = (ViewDocument) ((IView)activeView).getDocument();
84
            FLyrVect layer = viewdoc.getMapContext().getLayers().getFirstActiveVectorLayer();
85
            theStore = layer.getFeatureStore();
86
            if( theStore.isFeatureSelectionEmpty() ) {
87
                f = theStore.first();
88
            } else {
89
                f = theStore.getFeatureSelection().first();
90
            }
91
        } catch(Throwable t) {
92
            LOGGER.debug("Can't retrieve test feature",t);
93
        }
94
        LayoutReportActionImpl report = new LayoutReportActionImpl(theFactory, theStore, f);
95
        report.getSymbolTable().setVar("$LAYOUT", doc);
96
        report.getSymbolTable().setVar("$PAGE", 1);
97
        report.getSymbolTable().setVar("$PAGES", 1);
98
        return report;        
99
    }
100
    
101
    
102
    private final JsonObject json;
103
    private final FeatureStore store;
104
    private final FeatureQuery query;
105
    private FeatureSet selection;
106
    private Feature current_row;
107
    private MutableSymbolTable symbolTable;
108
    FeatureSymbolTable fSymbolTable;
109
    private boolean centerToCurrentRow;
110
    private boolean zoomToCurrentRow;
111
    private int bufferSize;
112
    private boolean selectCurrentRow;
113
    private boolean useInternalPdfViewer;
114
//    private FeatureSet set;
115
    private Iterable<Feature> set;
116
    private int featuresCount;
117
    private String viewTag;
118
    
119
    @SuppressWarnings("OverridableMethodCallInConstructor")
120
    private LayoutReportActionImpl(ReportActionFactory factory, FeatureStore store, Feature feature) {
121
        // Fake layoutReportAction constructor
122
        super(factory, null);
123
        try {
124
            this.selection = store.createFeatureSelection();
125
            ((FeatureSelection)this.selection).select(feature);
126
        } catch(Throwable t) {
127
            LOGGER.debug("Can't initialize selection",t);
128
        }
129
        this.store = store;
130
        this.query = store.createFeatureQuery(feature.createFilter());
131
        this.current_row = feature;
132
        this.json = Json.createObjectBuilder()
133
                .add(LAYOUT_REPORT_NAME, store.getName())
134
                .add(LAYOUT_REPORT_TYPE, LAYOUT_REPORT_ACTION_NAME)
135
                .add(LAYOUT_REPORT_LABEL, store.getName())
136
                .build();
137

    
138
        this.setReportName(this.json.getString(LAYOUT_REPORT_NAME, store.getName()));
139
        this.setReportLabel(this.json.getString(LAYOUT_REPORT_LABEL, this.getReportName()));
140
    }
141
    
142
    @SuppressWarnings("OverridableMethodCallInConstructor")
143
    public LayoutReportActionImpl(ReportActionFactory factory, FeatureStore store, FeatureQuery query, FeatureSet selection, final JsonObject json) {
144
        super(factory, null);
145
        this.json = json;
146
        this.setReportName(this.json.getString(LAYOUT_REPORT_NAME, store.getName()));
147
        this.setReportLabel(this.json.getString(LAYOUT_REPORT_LABEL, this.getReportName()));
148
        
149
        this.setCenterToCurrentRow(this.json.getBoolean(LAYOUT_REPORT_CENTER_TO_CURRENT_ROW, true));
150
        this.setZoomToCurrentRow(this.json.getBoolean(LAYOUT_REPORT_ZOOM_TO_CURRENT_ROW, true));
151
        this.setBufferSize(this.json.getInt(LAYOUT_REPORT_BUFFER_SIZE, 0));
152
        this.setSelectCurrentRow(this.json.getBoolean(LAYOUT_REPORT_SELECT_CURRENT_ROW, false));
153
        this.setViewTag(this.json.getString(LAYOUT_REPORT_VIEW_TAG, null));
154
        this.setUseInternalPdfViewer(this.json.getBoolean(LAYOUT_REPORT_USE_INTERNAL_PDF_VIEWER, true));
155
        
156
        this.selection = selection;
157
        this.store = store;
158
        this.query = query;
159
        this.current_row = null;
160
    }
161

    
162
    public Feature row() {
163
        return this.current_row;
164
    }
165
    
166
    private Iterable<Feature> features() {
167
        if( this.set == null ) {
168
                if(this.selection == null){
169
                try {
170
                    FeatureSet fset = store.getFeatureSet(query);
171
                    this.featuresCount = fset.size();
172
                    this.set = fset;
173
                } catch (DataException ex) {
174
                    throw new RuntimeException("Can't create dynamic-text report.", ex);
175
                }
176
            } else {
177
                this.featuresCount = this.selection.size();
178
                if(this.selection instanceof FeatureSelection){
179
                    this.set = this.store.getFeaturesIterable(((FeatureSelection)this.selection).referenceIterator());
180
                } else {
181
                    this.set = this.selection;
182
                }
183
            }
184
        }
185
        return this.set;
186
    }
187
    
188
    
189
    @Override
190
    public void actionPerformed(ActionEvent e) {
191
        try {
192
            String title = this.getReportLabel();
193
            String creator = "gvSIG-desktop";
194
            String subject = "Layout report";
195

    
196
            File pdfFile = ToolsLocator.getFoldersManager().getUniqueTemporaryFile("report.pdf");
197
            List<File> singlePdfFiles = new ArrayList();
198
            int pag = 0;
199
            for (Feature feature : features()) {
200
                File f = printReport(feature,++pag);
201
                singlePdfFiles.add(f);
202
            }
203
            
204
            PDFManager pdfManager = PDFLocator.getPDFManager();
205
            pdfManager.merge(singlePdfFiles, pdfFile, title, creator, subject);
206
            
207
            for (File singlePdfFile : singlePdfFiles) {
208
                singlePdfFile.delete();
209
            }
210
            
211
            if (this.isUseInternalPdfViewer()) {
212
                this.showEmbedded(pdfFile);
213
            } else {
214
                this.showExternal(pdfFile);
215
            }
216
            
217
            this.getStatus().terminate();
218
            
219
        } catch (Throwable t) {
220
            LOGGER.warn("Can't create layout report.", t);
221
            this.getStatus().abort();
222
        }
223
    }
224
    
225
    private File printReport(Feature feature, int page) throws Exception {
226
        this.current_row = feature;
227
        final LayoutPanel layout = this.loadTemplate();
228
        final LayoutContext context = layout.getLayoutContext();
229
        final Document document = layout.getDocument();
230

    
231
        this.getSymbolTable();
232
        fSymbolTable.setFeature(current_row);
233
        this.symbolTable.setVar("$LAYOUT", document);
234
        this.symbolTable.setVar("$PAGE", page);
235
        this.symbolTable.setVar("$PAGES", this.featuresCount);
236

    
237

    
238
        File pdfFile = null;
239
        Object previous_report = document.getProperty("$REPORT");
240
        try {
241
            document.setProperty("$REPORT", this);
242
            /*
243
                TODO: Aqui podriamos consultar en el json para ver si hacemos:
244
                x zoom al envelope de la geometria de current_row, 
245
                x si le aplicamos un buffer antes a ese envelop, 
246
                X si la seleccionamos... 
247
                - asi como con que vista tenemos que hacerlo. ????
248
             */
249
            int count = 1;
250
            MapContext mapContext = null;
251
            MapContext mapContextCandidate = null;
252
            for (IFFrame frame : context.getAllFFrames()) {
253
                if (frame instanceof FFrameView) {
254
                    if(mapContextCandidate == null){
255
                        mapContextCandidate = ((FFrameView) frame).getMapContext();
256
                    }
257
                    String frameTag = frame.getTag();
258
                    String countTag = "#"+count;
259
                    if(StringUtils.equalsIgnoreCase(this.getViewTag(), frameTag) ||
260
                       StringUtils.equalsIgnoreCase(this.getViewTag(), countTag)){
261
                        mapContext = ((FFrameView) frame).getMapContext();
262
                        break;
263
                    }
264
                }
265
            }
266
            if(mapContext == null){
267
                mapContext = mapContextCandidate;
268
            };
269
            
270
            FeatureStore storeInLayout = this.store;
271
            if (mapContext != null) {
272
                Envelope envelope = mapContext.getViewPort().getEnvelope();
273
                if (isZoomToCurrentRow()) {
274

    
275
                    envelope = this.current_row.getDefaultGeometry()
276
                            .getEnvelope().getGeometry().buffer(getBufferSize()).getEnvelope();
277
                    mapContext.getViewPort().setEnvelope(envelope);
278

    
279
                } else if (isCenterToCurrentRow()) {
280

    
281
                    envelope = this.current_row.getDefaultGeometry()
282
                            .getEnvelope().getGeometry().buffer(getBufferSize()).getEnvelope();
283

    
284
                    center(mapContext, envelope);
285

    
286
                } else {
287
                    //DO NOTHING ??
288
                }
289
                /*
290
                    FIXME: Habria que localizar el store en la vista y buscar ahi
291
                    la current_row para seleccionarla. Seleccionando directamente
292
                    la del store puede no funcionar por no ser el mismo store.
293
                 */
294
                for (FLayer layer : mapContext.getLayers().getLayers(null)) {
295
                    if (layer instanceof FLyrVect) {
296
                        FeatureStore layerStore = ((FLyrVect) layer).getFeatureStore();
297
                        if (layerStore != null) {
298
                            if (layerStore.getParameters().isTheSameStore(this.store.getParameters())) {
299
                                storeInLayout = layerStore;
300
                            }
301
                        }
302
                    }
303
                }
304
            }
305
            storeInLayout.getFeatureSelection().deselectAll();
306
            if (isSelectCurrentRow()) {
307
                storeInLayout.getFeatureSelection().select(current_row.getReference());
308
            }
309

    
310
            context.fullRefresh();
311
            layout.getLayoutControl().getLayoutDraw().initialize();
312

    
313
            pdfFile = ToolsLocator.getFoldersManager().getUniqueTemporaryFile("report.pdf");
314
            layout.layoutToPDF(pdfFile);
315
        } finally {
316
            document.setProperty("$REPORT", previous_report);
317
        }
318

    
319
        return pdfFile;
320
    }
321

    
322
    private void center(MapContext mapContext, Envelope envelope) throws LocatorException, CreateEnvelopeException {
323
        ViewPort viewPort = mapContext.getViewPort();
324
        Envelope oldExtent = viewPort.getAdjustedEnvelope();
325
        double oldCenterX = oldExtent.getCenter(0);
326
        double oldCenterY = oldExtent.getCenter(1);
327
        double centerX = envelope.getCenter(0);
328
        double centerY = envelope.getCenter(1);
329
        Point2D.Double center = new Point2D.Double(centerX, centerY);
330
        double movX = centerX - oldCenterX;
331
        double movY = centerY - oldCenterY;
332
        
333
        double minx = oldExtent.getMinimum(0) + movX;
334
        double miny = oldExtent.getMinimum(1) + movY;
335
        double maxX = oldExtent.getMaximum(0) + movX;
336
        double maxY = oldExtent.getMaximum(1) + movY;
337
        Envelope extent = GeometryLocator.getGeometryManager().createEnvelope(
338
                minx, miny,
339
                maxX, maxY,
340
                Geometry.SUBTYPES.GEOM2D);
341
        viewPort.setEnvelope(extent);
342
    }
343

    
344
    private void showEmbedded(File pdfFile) throws IOException {
345
        final WindowManager windowManager = ToolsSwingLocator.getWindowManager();
346
        final PDFSwingManager pdfSwingManager = PDFSwingLocator.getPDFSwingManager();
347
        final PDFManager pdfManager = PDFLocator.getPDFManager();
348

    
349
        final PDFDocument pdfdoc = pdfManager.createPDFDocument(pdfFile);            
350
        PDFViewer viewer = pdfSwingManager.createPDFViewer();
351
        viewer.put(pdfdoc);
352
        viewer.setMode(PDFViewer.MODE_LIGHT);
353

    
354
        JComponent comp = viewer.asJComponent();
355
        Dimension size = ToolsSwingUtils.ensureRowsCols(comp.getPreferredSize(), 20, 100, 40, 150);
356
        comp.setSize(size);
357

    
358
        String title = "Report: " + this.getLabel();
359
        windowManager.showWindow(
360
                comp,
361
                title,
362
                WindowManager.MODE.WINDOW
363
        );
364
    }
365

    
366
    private void showExternal(File pdfFile) {
367
        DesktopOpen desktop = ToolsUtilLocator.getToolsUtilManager().createDesktopOpen();
368
        desktop.open(pdfFile);
369
    }
370
    
371
    private LayoutPanel loadTemplate() throws Exception {
372
        ResourcesStorage resources = store.getResourcesStorage();
373
        if (resources == null) {
374
            return null;
375
        }
376
        String templateName = this.json.getString(LAYOUT_REPORT_TEMPLATE_NAME, LAYOUT_REPORT_DEFAULT_TEMPLATE_NAME); // "1.layout"...
377
        ResourcesStorage.Resource resource = resources.getResource(templateName);
378
        InputStream is = null;
379
        try {
380
            is = resource.asInputStream();
381
            PersistenceManager persistenceManager = ToolsLocator.getPersistenceManager();
382
            PersistentState persistentState = persistenceManager.loadState(is);
383

    
384
            LayoutPanel layout = (LayoutPanel) persistenceManager.create(persistentState);
385

    
386
            return layout;
387
        } finally {
388
            IOUtils.closeQuietly(is);
389
        }
390
    }
391
    
392
    public MutableSymbolTable getSymbolTable() {
393
        if( this.symbolTable == null ) {
394
            this.symbolTable = ExpressionUtils.createSymbolTable();
395
            fSymbolTable = DALLocator.getDataManager().createFeatureSymbolTable();
396
            fSymbolTable.setFeature(current_row);
397
            this.symbolTable.addSymbolTable(fSymbolTable);
398
            this.symbolTable.setVar("$REPORT", this);
399
        }
400
        return this.symbolTable;
401
    }
402

    
403
    @Override
404
    public String evaluateDynamicText(String s) {
405
        ExpressionEvaluatorManager manager = ExpressionEvaluatorLocator.getExpressionEvaluatorManager();
406
        if( !manager.isDynamicText(s) ) {
407
            return s;
408
        }
409
        String x = manager.evaluateDynamicText(
410
                this.getSymbolTable(), 
411
                s, 
412
                null, 
413
                this.store.getResourcesStorage()
414
        );
415
        return x;
416
    }
417

    
418
    @Override
419
    public boolean isCenterToCurrentRow() {
420
        return this.centerToCurrentRow;
421
    }
422

    
423
    @Override
424
    public void setCenterToCurrentRow(boolean centerToCurrentRow) {
425
        this.centerToCurrentRow = centerToCurrentRow;
426
    }
427
    
428
    @Override
429
    public boolean isZoomToCurrentRow() {
430
        return this.zoomToCurrentRow;
431
    }
432

    
433
    @Override
434
    public void setZoomToCurrentRow(boolean zoomToCurrentRow) {
435
        this.zoomToCurrentRow = zoomToCurrentRow;
436
    }
437
    
438
    @Override
439
    public int getBufferSize() {
440
        return bufferSize;
441
    }
442

    
443
    @Override
444
    public void setBufferSize(int bufferSize) {
445
        this.bufferSize = bufferSize;
446
    }
447
    
448
    @Override
449
    public boolean isSelectCurrentRow() {
450
        return selectCurrentRow;
451
    }
452
    
453
    @Override
454
    public void setSelectCurrentRow(boolean selectCurrentRow) {
455
        this.selectCurrentRow = selectCurrentRow;
456
    }
457
    
458
    @Override
459
    public String getViewTag() {
460
        return viewTag;
461
    }
462

    
463
    @Override
464
    public void setViewTag(String viewTag) {
465
        this.viewTag = viewTag;
466
    }
467
    
468
    public  boolean isUseInternalPdfViewer() {
469
        return useInternalPdfViewer;
470
    }
471

    
472
    @Override
473
    public void setUseInternalPdfViewer(boolean useInternalPdfViewer) {
474
        this.useInternalPdfViewer = useInternalPdfViewer;
475
    }
476
   
477
}