001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.io;
003
004import java.beans.PropertyChangeListener;
005import java.beans.PropertyChangeSupport;
006import java.io.File;
007import java.util.ArrayList;
008import java.util.Collections;
009import java.util.Comparator;
010import java.util.List;
011
012import javax.swing.table.DefaultTableModel;
013
014import org.openstreetmap.josm.gui.layer.OsmDataLayer;
015
016public class SaveLayersModel extends DefaultTableModel {
017    public static final String MODE_PROP = SaveLayerInfo.class.getName() + ".mode";
018    public enum Mode {
019        EDITING_DATA,
020        UPLOADING_AND_SAVING
021    }
022
023    private List<SaveLayerInfo> layerInfo;
024    private Mode mode;
025    private PropertyChangeSupport support;
026
027    // keep in sync with how the columns are ordered in SaveLayersTableColumnModel#build
028    private static final int columnFilename = 0;
029    private static final int columnActions = 2;
030
031    /**
032     * Constructs a new {@code SaveLayersModel}.
033     */
034    public SaveLayersModel() {
035        mode = Mode.EDITING_DATA;
036        support = new PropertyChangeSupport(this);
037    }
038
039    public void addPropertyChangeListener(PropertyChangeListener l) {
040        support.addPropertyChangeListener(l);
041    }
042
043    public void removePropertyChangeListener(PropertyChangeListener l) {
044        support.removePropertyChangeListener(l);
045    }
046
047    protected void fireModeChanged(Mode oldValue, Mode newValue) {
048        support.firePropertyChange(MODE_PROP, oldValue, newValue);
049    }
050
051    public void setMode(Mode newValue) {
052        Mode oldValue = this.mode;
053        this.mode = newValue;
054        fireModeChanged(oldValue, newValue);
055    }
056
057    public Mode getMode() {
058        return mode;
059    }
060
061    public void populate(List<OsmDataLayer> layers) {
062        layerInfo = new ArrayList<>();
063        if (layers == null) return;
064        for (OsmDataLayer layer: layers) {
065            layerInfo.add(new SaveLayerInfo(layer));
066        }
067        Collections.sort(
068                layerInfo,
069                new Comparator<SaveLayerInfo>() {
070                    @Override
071                    public int compare(SaveLayerInfo o1, SaveLayerInfo o2) {
072                        return o1.compareTo(o2);
073                    }
074                }
075        );
076        fireTableDataChanged();
077    }
078
079    @Override
080    public int getRowCount() {
081        if (layerInfo == null) return 0;
082        return layerInfo.size();
083    }
084
085    @Override
086    public Object getValueAt(int row, int column) {
087        if (layerInfo == null) return null;
088        return layerInfo.get(row);
089    }
090
091    @Override
092    public boolean isCellEditable(int row, int column) {
093        return column == columnFilename || column == columnActions;
094    }
095
096    @Override
097    public void setValueAt(Object value, int row, int column) {
098        switch(column) {
099        case columnFilename:
100            this.layerInfo.get(row).setFile((File)value);
101            this.layerInfo.get(row).setDoSaveToFile(true);
102            break;
103        case columnActions:
104            boolean[] values = (boolean[]) value;
105            this.layerInfo.get(row).setDoUploadToServer(values[0]);
106            this.layerInfo.get(row).setDoSaveToFile(values[1]);
107            break;
108        }
109        fireTableDataChanged();
110    }
111
112    public List<SaveLayerInfo> getSafeLayerInfo() {
113        return this.layerInfo;
114    }
115
116    public List<SaveLayerInfo> getLayersWithoutFilesAndSaveRequest() {
117        List<SaveLayerInfo> ret = new ArrayList<>();
118        for (SaveLayerInfo info: layerInfo) {
119            if (info.isDoSaveToFile() && info.getFile() == null) {
120                ret.add(info);
121            }
122        }
123        return ret;
124    }
125
126    public List<SaveLayerInfo> getLayersWithIllegalFilesAndSaveRequest() {
127        List<SaveLayerInfo> ret =new ArrayList<>();
128        for (SaveLayerInfo info: layerInfo) {
129            if (info.isDoSaveToFile() && info.getFile() != null && info.getFile().exists() && !info.getFile().canWrite()) {
130                ret.add(info);
131            }
132        }
133        return ret;
134    }
135
136    public List<SaveLayerInfo> getLayersWithConflictsAndUploadRequest() {
137        List<SaveLayerInfo> ret =new ArrayList<>();
138        for (SaveLayerInfo info: layerInfo) {
139            if (info.isDoUploadToServer() && !info.getLayer().getConflicts().isEmpty()) {
140                ret.add(info);
141            }
142        }
143        return ret;
144    }
145
146    public List<SaveLayerInfo> getLayersToUpload() {
147        List<SaveLayerInfo> ret =new ArrayList<>();
148        for (SaveLayerInfo info: layerInfo) {
149            if (info.isDoUploadToServer()) {
150                ret.add(info);
151            }
152        }
153        return ret;
154    }
155
156    public List<SaveLayerInfo> getLayersToSave() {
157        List<SaveLayerInfo> ret =new ArrayList<>();
158        for (SaveLayerInfo info: layerInfo) {
159            if (info.isDoSaveToFile()) {
160                ret.add(info);
161            }
162        }
163        return ret;
164    }
165
166    public void setUploadState(OsmDataLayer layer, UploadOrSaveState state) {
167        SaveLayerInfo info = getSaveLayerInfo(layer);
168        if (info != null) {
169            info.setUploadState(state);
170        }
171        fireTableDataChanged();
172    }
173
174    public void setSaveState(OsmDataLayer layer, UploadOrSaveState state) {
175        SaveLayerInfo info = getSaveLayerInfo(layer);
176        if (info != null) {
177            info.setSaveState(state);
178        }
179        fireTableDataChanged();
180    }
181
182    public SaveLayerInfo getSaveLayerInfo(OsmDataLayer layer) {
183        for (SaveLayerInfo info: this.layerInfo) {
184            if (info.getLayer() == layer)
185                return info;
186        }
187        return null;
188    }
189
190    public void resetSaveAndUploadState() {
191        for (SaveLayerInfo info: layerInfo) {
192            info.setSaveState(null);
193            info.setUploadState(null);
194        }
195    }
196
197    public boolean hasUnsavedData() {
198        for (SaveLayerInfo info: layerInfo) {
199            if (info.isDoUploadToServer() && ! UploadOrSaveState.OK.equals(info.getUploadState()))
200                return true;
201            if (info.isDoSaveToFile() && ! UploadOrSaveState.OK.equals(info.getSaveState()))
202                return true;
203        }
204        return false;
205    }
206
207    public int getNumCancel() {
208        int ret = 0;
209        for (SaveLayerInfo info: layerInfo) {
210            if (UploadOrSaveState.CANCELED.equals(info.getSaveState())
211                    || UploadOrSaveState.CANCELED.equals(info.getUploadState())) {
212                ret++;
213            }
214        }
215        return ret;
216    }
217
218    public int getNumFailed() {
219        int ret = 0;
220        for (SaveLayerInfo info: layerInfo) {
221            if (UploadOrSaveState.FAILED.equals(info.getSaveState())
222                    || UploadOrSaveState.FAILED.equals(info.getUploadState())) {
223                ret++;
224            }
225        }
226        return ret;
227    }
228}