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 / extension / reportfromlayout / ConfigureReportFromLayout.java @ 1607

History | View | Annotate | Download (21.6 KB)

1
/*
2
 * To change this license header, choose License Headers in Project Properties.
3
 * To change this template file, choose Tools | Templates
4
 * and open the template in the editor.
5
 */
6
package org.gvsig.app.extension.reportfromlayout;
7

    
8
import java.awt.Dimension;
9
import java.awt.event.ActionEvent;
10
import java.awt.event.ActionListener;
11
import java.io.ByteArrayOutputStream;
12
import java.io.InputStream;
13
import java.nio.charset.StandardCharsets;
14
import java.util.List;
15
import java.util.function.Predicate;
16
import javax.json.JsonObject;
17
import javax.swing.DefaultComboBoxModel;
18
import javax.swing.JComponent;
19
import javax.swing.JOptionPane;
20
import javax.swing.SwingUtilities;
21
import javax.swing.event.DocumentEvent;
22
import javax.swing.event.DocumentListener;
23
import javax.swing.event.TreeSelectionEvent;
24
import org.apache.commons.codec.binary.Hex;
25
import org.apache.commons.io.IOUtils;
26
import org.apache.commons.lang3.StringUtils;
27
import org.gvsig.app.ApplicationLocator;
28
import org.gvsig.app.gui.styling.SymbolSelector;
29
import org.gvsig.app.project.documents.Document;
30
import org.gvsig.app.project.documents.layout.LayoutDocument;
31
import org.gvsig.app.project.documents.layout.fframes.FFrameView;
32
import org.gvsig.app.project.documents.layout.fframes.IFFrame;
33
import org.gvsig.app.project.documents.layout.report.LayoutReportAction;
34
import org.gvsig.app.project.documents.layout.report.LayoutReportActionFactory;
35
import org.gvsig.app.project.documents.layout.report.LayoutReportActionImpl;
36
import org.gvsig.app.project.documents.view.legend.gui.ISymbolSelector;
37
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
38
import org.gvsig.fmap.dal.feature.FeatureStore;
39
import org.gvsig.fmap.dal.swing.DALSwingLocator;
40
import org.gvsig.fmap.dal.swing.DataSwingManager;
41
import org.gvsig.fmap.dal.swing.report.ReportAction;
42
import org.gvsig.fmap.dal.swing.storesrepository.StoresRepositoryController;
43
import org.gvsig.fmap.mapcontext.MapContextLocator;
44
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
45
import org.gvsig.json.Json;
46
import org.gvsig.json.JsonObjectBuilder;
47
import org.gvsig.tools.ToolsLocator;
48
import org.gvsig.tools.dispose.DisposeUtils;
49
import org.gvsig.tools.i18n.I18nManager;
50
import org.gvsig.tools.persistence.PersistenceManager;
51
import org.gvsig.tools.persistence.PersistentState;
52
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
53
import org.gvsig.tools.swing.api.ListElement;
54
import org.gvsig.tools.swing.api.ToolsSwingLocator;
55
import org.gvsig.tools.swing.api.ToolsSwingManager;
56
import org.gvsig.tools.swing.api.ToolsSwingUtils;
57
import org.gvsig.tools.swing.api.documentfilters.PositiveDoubleDocumentFilter;
58
import org.gvsig.tools.swing.api.threadsafedialogs.ThreadSafeDialogsManager;
59
import org.gvsig.tools.swing.api.windowmanager.Dialog;
60
import org.gvsig.tools.swing.api.windowmanager.WindowManager;
61
import org.gvsig.tools.swing.api.windowmanager.WindowManager_v2;
62
import org.gvsig.tools.util.LabeledValue;
63
import org.gvsig.tools.util.LabeledValueImpl;
64
import org.slf4j.Logger;
65
import org.slf4j.LoggerFactory;
66

    
67
/**
68
 *
69
 * @author fdiaz
70
 */
71
public class ConfigureReportFromLayout extends ConfigureReportFromLayoutPanelView {
72

    
73
    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigureReportFromLayout.class);
74

    
75
    private StoresRepositoryController treeSourceController;
76
    private FeatureStore source;
77
    private Dialog dialog;
78
    private ISymbol highlightSymbol;
79

    
80
    public ConfigureReportFromLayout() {
81
        this.initComponents();
82

    
83
    }
84
    
85
    private void initComponents() {
86

    
87
        DataSwingManager dataSwingManager = DALSwingLocator.getSwingManager();
88
        translate();
89

    
90
        fillCboLayout();
91
        
92
        this.cboLayout.addActionListener(new ActionListener() {
93
            @Override
94
            public void actionPerformed(ActionEvent e) {
95
                doChangeLayout();
96
            }
97
        });
98
        
99
        this.treeSourceController = dataSwingManager.createStoresRepositoryController(this.treeSource);
100
        this.treeSource.addTreeSelectionListener((TreeSelectionEvent e) -> {
101
            doChangeSource();
102
            doUpdateComponents();
103
        });
104
        
105
        this.cboReport.addActionListener((ActionEvent e) -> {
106
            doChangeReport();
107
        });
108
        
109
        this.txtIdentifier.getDocument().addDocumentListener(new DocumentListener() {
110
            @Override
111
            public void insertUpdate(DocumentEvent e) {
112
                doUpdateComponents();
113
            }
114

    
115
            @Override
116
            public void removeUpdate(DocumentEvent e) {
117
                doUpdateComponents();
118
            }
119

    
120
            @Override
121
            public void changedUpdate(DocumentEvent e) {
122
               doUpdateComponents();
123
            }
124
        });
125
        
126
        this.chkZoomToCurrentRow.addActionListener((ActionEvent e) -> {
127
            doUpdateComponents();
128
        });
129
        
130
        this.btnSelectSymbol.addActionListener((ActionEvent e) -> {
131
            doSelectSymbol();
132
        });
133
        
134
        ToolsSwingManager toolsSwingManager = ToolsSwingLocator.getToolsSwingManager();
135
        
136
        PositiveDoubleDocumentFilter.install(txtBufferSize);
137
        
138
        Dimension screensize = ApplicationLocator.getApplicationManager().getUIManager().getInternalSize();
139
        ToolsSwingUtils.ensureHeightWitdh(
140
                this, 
141
                Math.max(3*(screensize.height/4), ToolsSwingUtils.rows2px(80)),
142
                Math.max(2*(screensize.width/4), ToolsSwingUtils.cols2px(35)), 
143
                7*(screensize.height/8), 
144
                3*(screensize.width/4)
145
        );        
146

    
147
        SwingUtilities.invokeLater(this::doUpdateComponents);
148

    
149
    }
150

    
151
    private void doChangeSource() {
152
        FeatureStore theSource = this.treeSourceController.getSelectedFeatureStore();
153
        if( theSource==null ) {
154
            return;
155
        }
156
        if(this.source != null){
157
            DisposeUtils.disposeQuietly(this.source);
158
        }
159
        this.source = theSource;
160
        fillCboReport();
161
        doUpdateComponents();
162
    }
163
    
164
    private void doChangeLayout() {
165
        fillCboView();
166
        doUpdateComponents();
167
    }
168
    
169
    private void doSelectSymbol() {
170

    
171
        if(this.source == null){
172
            return;
173
        }
174
        FeatureAttributeDescriptor geomAttr = this.source.getDefaultFeatureTypeQuietly().getDefaultGeometryAttribute();
175
        if(geomAttr == null){
176
            return;
177
        }
178
        int geomType = geomAttr.getGeomType().getType();
179

    
180
        if(this.highlightSymbol == null) {
181
            this.highlightSymbol = MapContextLocator.getMapContextManager().createSymbol(geomType);
182
        }
183
        ISymbolSelector symSel = SymbolSelector.createSymbolSelector(this.highlightSymbol, geomType);
184

    
185
        WindowManager_v2 windowManager = (WindowManager_v2) ToolsSwingLocator.getWindowManager();
186
        windowManager.showWindow((JComponent)symSel, "_Symbol", WindowManager.MODE.DIALOG);
187
        this.highlightSymbol = (ISymbol) symSel.getSelectedObject();
188

    
189
    }
190
    
191

    
192
    private void doUpdateComponents() {
193
        this.treeSourceController.setEnabled(true);
194

    
195
        this.cboReport.setEnabled(this.source != null);
196
        
197
        this.txtBufferSize.setEnabled(this.chkZoomToCurrentRow.isSelected());
198
        
199
        if(this.dialog != null){
200
            boolean enabled = (this.source != null) && (this.getLayoutDocument() != null) && StringUtils.isNotBlank(this.txtIdentifier.getText());
201
            this.dialog.setButtonEnabled(WindowManager_v2.BUTTON_OK, enabled);
202
        }
203
    }
204
    
205
    private void fillCboReport() {
206
        DataSwingManager dataSwingManager = DALSwingLocator.getDataSwingManager();
207
        DefaultComboBoxModel<LabeledValue<ReportAction>> model = new DefaultComboBoxModel();
208
        if(this.source == null) {
209
            this.cboReport.setModel(model);
210
            return;
211
        }
212
        List<ReportAction> reports = dataSwingManager.getReportActions(source, (Predicate<JsonObject>) (JsonObject t) -> LayoutReportActionFactory.isJsonApplicable(t));
213
        
214
        model.addElement(new LabeledValueImpl<>("", null));
215
        for (ReportAction report : reports) {
216
            model.addElement(new LabeledValueImpl<>(report.getReportLabel(), report));
217
        }
218
        cboReport.setModel(model);
219

    
220
    }
221
  
222
    List<Document> getLayouts() {
223

    
224
        List<Document> layouts = ApplicationLocator.getProjectManager().getCurrentProject().getDocuments(LayoutDocument.class);
225

    
226
        return layouts;
227

    
228
    }
229

    
230

    
231
    
232
    private void fillCboLayout() {
233
        DefaultComboBoxModel<LabeledValue<LayoutDocument>> model = new DefaultComboBoxModel();
234
        List<Document> layouts = getLayouts();
235
        
236
        for (Document layout : layouts) {
237
            if(layout instanceof LayoutDocument){
238
                model.addElement(new LabeledValueImpl<>(layout.getName(), (LayoutDocument)layout));
239
            }
240
        }
241
        cboLayout.setModel(model);
242
        fillCboView();
243

    
244
    }
245
    
246
    private void fillCboView() {
247
        LayoutDocument layout = getLayoutDocument();
248
        DefaultComboBoxModel<LabeledValue<String>> model = new DefaultComboBoxModel();
249
        if (layout != null) {
250
            int n = 1;
251
            for (IFFrame frame : layout.getLayoutContext().getAllFFrames()) {
252
                if (frame instanceof FFrameView) {
253
                    String tag = frame.getTag();
254
                    if(StringUtils.startsWith(tag, "#") && !StringUtils.equals(tag, "#"+n)){
255
                        model.addElement(new LabeledValueImpl<>(tag+" (invalid tag)",tag));
256
                    } else {
257
                        if(StringUtils.isBlank(tag)){
258
                            tag = "#"+n;
259
                        }
260
                        model.addElement(new LabeledValueImpl<>(tag,tag));
261
                    }
262
                    n++;
263
                }
264
            }
265
        }
266
        this.cboView.setModel(model);
267
    }
268
    
269
    private LayoutReportAction getReportAction(){
270
        LabeledValue<LayoutReportAction> selected = (LabeledValue<LayoutReportAction>)cboReport.getSelectedItem();
271
        if(selected == null){
272
            return null;
273
        }
274
        return selected.getValue();
275
    }
276
    
277
    private LayoutDocument getLayoutDocument(){
278
        LabeledValue<LayoutDocument> selected = (LabeledValue<LayoutDocument>)cboLayout.getSelectedItem();
279
        if(selected == null){
280
            return null;
281
        }
282
        return selected.getValue();
283
    }
284
    
285
    private String getViewTag(){
286
        LabeledValue<String> selected = (LabeledValue<String>)cboView.getSelectedItem();
287
        if(selected == null){
288
            return null;
289
        }
290
        return selected.getValue();
291
    }
292
    
293
    public void fetch(ConfigureReportFromLayoutParameters params){
294
        params.setLayout(this.getLayoutDocument());
295
        params.setSource(this.source);
296
        params.setIdentifier(this.txtIdentifier.getText());
297
        params.setLabel(this.txtLabel.getText());
298
        
299
        params.setCenterToCurrentRow(this.chkCenterToCurrentRow.isSelected());
300
        params.setZoomToCurrentRow(this.chkZoomToCurrentRow.isSelected());
301
        double bufferSize = PositiveDoubleDocumentFilter.getValue(this.txtBufferSize);
302
        params.setBufferSize(bufferSize);
303
        params.setViewTag(this.getViewTag());
304
        params.setUseIntervalPdfViewer(this.chkUseInternalPdfViewer.isSelected());
305
        params.setHighlightRecord(this.chkHighlightRecord.isSelected());
306
        params.setHighlightSymbol(this.highlightSymbol);
307
    }
308

    
309
    private void translate() {
310
        ToolsSwingManager manager = ToolsSwingLocator.getToolsSwingManager();
311
        manager.translate(lblLayout);
312
        manager.translate(lblSource);
313
        manager.translate(lblReport);
314
        manager.translate(lblIdentifier);
315
        manager.translate(lblLabel);
316
        manager.translate(lblViewSeparator);
317
        manager.translate(lblView);
318
        manager.translate(chkCenterToCurrentRow);
319
        manager.translate(chkZoomToCurrentRow);
320
        manager.translate(lblBufferSize);
321
        manager.translate(chkUseInternalPdfViewer);
322
        manager.translate(txtBufferSize);
323
        manager.translate(chkHighlightRecord);
324
        manager.translate(btnSelectSymbol);
325
    }
326
    
327
    public boolean doConfigureReportFromLayout(ConfigureReportFromLayoutParameters params) {
328
        LayoutDocument layout = params.getLayout();
329
        FeatureStore source = params.getSource();
330
        String identifier = params.getIdentifier();
331
        String label = params.getLabel();
332
        
333
        ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
334
        I18nManager i18n = ToolsLocator.getI18nManager();
335
        
336
        if(layout == null){
337
            dialogs.messageDialog(
338
                    i18n.getTranslation("_Layout_cant_be_null"), 
339
                    null,
340
                    "_Configure_report_from_layout", 
341
                    JOptionPane.WARNING_MESSAGE);
342
            return false;
343
        }
344

    
345
        if(source == null){
346
            dialogs.messageDialog(
347
                    i18n.getTranslation("_Source_cant_be_null"), 
348
                    null,
349
                    "_Configure_report_from_layout", 
350
                    JOptionPane.WARNING_MESSAGE);
351
            return false;
352
        }
353

    
354
        if(StringUtils.isBlank(identifier)){
355
            dialogs.messageDialog(
356
                    i18n.getTranslation("_Identifier_cant_be_null"), 
357
                    null,
358
                    "_Configure_report_from_layout", 
359
                    JOptionPane.WARNING_MESSAGE);
360
            return false;
361
        }
362
        
363
        boolean centerToCurrentRow = params.isCenterToCurrentRow();
364
        boolean zoomToCurrentRow = params.isZoomToCurrentRow();
365
        double bufferSize = params.getBufferSize();
366
        boolean highlightRecord = params.isHighlightRecord();
367
        ISymbol highlightSymbol = params.getHighlightSymbol();
368
        boolean useInternalPdfViewer = params.isUseIntervalPdfViewer();
369
        String viewTag = params.getViewTag();
370
                
371
        return doConfigureReportFromLayout(
372
                source, 
373
                layout, 
374
                identifier, 
375
                label, 
376
                centerToCurrentRow, 
377
                zoomToCurrentRow, 
378
                bufferSize, 
379
                highlightRecord,
380
                highlightSymbol,
381
                viewTag,
382
                useInternalPdfViewer);
383
        
384
        
385
    }
386
    
387
    public boolean doConfigureReportFromLayout(
388
            FeatureStore store, 
389
            LayoutDocument layout, 
390
            String name, 
391
            String label,
392
            boolean centerToCurrentRow,
393
            boolean zoomToCurrentRow,
394
            double bufferSize,
395
            boolean highlightRecord,
396
            ISymbol highlightSymbol,
397
            String viewTag,
398
            boolean useInternalPdfViewer
399
    ) {
400
        ResourcesStorage.Resource resource = null;
401
        ResourcesStorage.Resource resourceLayout = null;
402
        boolean selfContained = layout.isPersistIndependent();
403
        try {
404
            ResourcesStorage resources = store.getResourcesStorage();
405
            
406
            String resourceName = getResourceName(resources, name);
407
            if(resourceName == null){
408
                resourceName = getNextResourceName(resources, "report");
409
            }
410
            
411
            String templateName = LayoutReportActionFactory.LAYOUT_REPORT_ACTION_NAME;
412
            if(StringUtils.contains(resourceName, resources.getSeparator())){
413
                templateName = StringUtils.replaceIgnoreCase(resourceName, resources.getSeparator()+"report", resources.getSeparator()+LayoutReportActionFactory.LAYOUT_REPORT_ACTION_NAME);
414
            }
415
            JsonObjectBuilder jsonBuilder = Json.createObjectBuilder();
416
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_NAME, name);
417
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_TYPE, LayoutReportActionFactory.LAYOUT_REPORT_ACTION_NAME);
418
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_LABEL, label);
419
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_TEMPLATE_NAME, templateName);
420
            if(highlightSymbol != null){
421
                jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_HIGHLIGHT_SYMBOL, this.toString(highlightSymbol));
422
            }
423
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_CENTER_TO_CURRENT_ROW, centerToCurrentRow);
424
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_ZOOM_TO_CURRENT_ROW, zoomToCurrentRow);
425
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_BUFFER_SIZE, bufferSize);
426
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_HIGHLIGHT_RECORD, highlightRecord);
427
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_VIEW_TAG, viewTag);
428
            jsonBuilder.add(LayoutReportActionImpl.LAYOUT_REPORT_USE_INTERNAL_PDF_VIEWER, useInternalPdfViewer);
429
            
430
            resource = resources.getResource(resourceName);
431
            IOUtils.write(jsonBuilder.toString(), resource.asOutputStream(), StandardCharsets.UTF_8);
432
            
433
            resourceLayout = resources.getResource(templateName);
434
            PersistenceManager persistenceManager = ToolsLocator.getPersistenceManager();
435
            layout.setPersistIndependent(true);
436
            PersistentState persistentState = persistenceManager.getState(layout.getMainWindow());
437
            persistenceManager.saveState(persistentState, resourceLayout.asOutputStream());
438
            ((JComponent)dialog).setVisible(false);
439
            return true;
440
        } catch (Exception ex) {
441
            ThreadSafeDialogsManager dialogs = ToolsSwingLocator.getThreadSafeDialogsManager();
442
            I18nManager i18n = ToolsLocator.getI18nManager();
443
            dialogs.messageDialog(
444
                    i18n.getTranslation("_Cant_configure_report_from_layout"), 
445
                    null,
446
                    "_Configure_report_from_layout", 
447
                    JOptionPane.WARNING_MESSAGE);
448
            return false;
449
        } finally {
450
            layout.setPersistIndependent(selfContained);
451
            IOUtils.closeQuietly(resource);
452
            IOUtils.closeQuietly(resourceLayout);
453
        }
454
        
455
    }
456
    
457
    private String toString(ISymbol symbol){
458
        try {
459
            if(symbol == null){
460
                return null;
461
            }
462
            PersistenceManager persistenceManager = ToolsLocator.getPersistenceManager();
463
            PersistentState state = persistenceManager.getState(symbol);
464
            ByteArrayOutputStream out = new ByteArrayOutputStream();
465
            persistenceManager.saveState(state, out);
466
            return Hex.encodeHexString(out.toByteArray());
467
        } catch (Exception ex) {
468
            throw new RuntimeException("Can't persist symbol", ex);
469
        }
470
    }
471
    
472
    private String getNextResourceName(ResourcesStorage resources, String resourceName){
473
        List<ResourcesStorage.Resource> reports = resources.getResources(resourceName);
474
        if(reports == null || reports.isEmpty()){
475
            return resourceName;
476
        }
477
        int n = -1;
478
        for (ResourcesStorage.Resource report : reports) {
479
            if(StringUtils.contains(report.getName(), resources.getSeparator())){
480
                String[] s = StringUtils.split(report.getName(), resources.getSeparator());
481
                n = Math.max(n, Integer.parseInt(s[0]));
482
            } else {
483
                n=0;
484
            }
485
        }
486
        
487
        if (n < 0) {
488
            return resourceName;
489
        }
490
        
491
        n++;
492
        return String.valueOf(n) + resources.getSeparator() + resourceName;
493

    
494
        
495
    }
496
    
497
    private String getResourceName(ResourcesStorage resources, String reportName) {
498
        try {
499
            if (resources != null) {
500
                List<ResourcesStorage.Resource> reportsResources = resources.getResources("report");
501
                if (reportsResources != null && !reportsResources.isEmpty()) {
502
                    for (ResourcesStorage.Resource resource : reportsResources) {
503
                        InputStream is = null;
504
                        try {
505
                            is = resource.asInputStream();
506
                            JsonObject json = javax.json.Json.createReader(is).readObject();
507
                            String name = json.getString(LayoutReportActionImpl.LAYOUT_REPORT_NAME, null);
508
                            if(StringUtils.equalsIgnoreCase(name, reportName)){
509
                                return resource.getName();
510
                            }
511
                        } catch (Exception ex) {
512
                            LOGGER.warn("Can't load report form resource (" + resource.getURL() + ")", ex);
513
                        } finally {
514
                            IOUtils.closeQuietly(is);
515
                        }
516
                        DisposeUtils.disposeQuietly(resource);
517
                    }
518
                }
519
            }
520
        } finally {
521
            DisposeUtils.disposeQuietly(resources);
522
        }
523
        return null;
524
    }
525
    
526

    
527
    private void doChangeReport() {
528
        LayoutReportAction report = getReportAction();
529
        if(report == null){
530
            this.txtIdentifier.setText("");
531
            this.txtLabel.setText("");
532
        } else {
533
            this.txtIdentifier.setText(report.getReportName());
534
            this.txtLabel.setText(report.getReportLabel());
535
            this.chkCenterToCurrentRow.setSelected(report.isCenterToCurrentRow());
536
            this.chkZoomToCurrentRow.setSelected(report.isZoomToCurrentRow());
537
            PositiveDoubleDocumentFilter.setValue(this.txtBufferSize,report.getBufferSize());
538
            this.chkHighlightRecord.setSelected(report.isHighlightRecord());
539
            ListElement.setSelected(this.cboView, report.getViewTag());
540
            this.chkUseInternalPdfViewer.setSelected(report.isUseInternalPdfViewer());
541
        }
542
        doUpdateComponents();
543
    }
544

    
545
    void setDialog(Dialog dialog) {
546
        this.dialog = dialog;
547
    }
548
    
549

    
550
    
551
}