Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.editing.app / org.gvsig.editing.app.mainplugin / src / main / java / org / gvsig / editing / clipboard / util / FeatureTextUtils.java @ 41610

History | View | Annotate | Download (7.87 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.editing.clipboard.util;
25

    
26
import java.awt.Toolkit;
27
import java.awt.datatransfer.DataFlavor;
28
import java.util.ArrayList;
29
import java.util.List;
30

    
31
import org.gvsig.andami.PluginServices;
32
import org.gvsig.fmap.dal.exception.DataException;
33
import org.gvsig.fmap.dal.feature.EditableFeature;
34
import org.gvsig.fmap.dal.feature.Feature;
35
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
36
import org.gvsig.fmap.dal.feature.FeatureSet;
37
import org.gvsig.fmap.dal.feature.FeatureStore;
38
import org.gvsig.fmap.dal.feature.FeatureType;
39
import org.gvsig.fmap.geom.DataTypes;
40
import org.gvsig.fmap.geom.Geometry;
41
import org.gvsig.fmap.geom.GeometryLocator;
42
import org.gvsig.fmap.geom.GeometryManager;
43
import org.gvsig.fmap.geom.operation.GeometryOperationContext;
44
import org.gvsig.tools.dispose.DisposableIterator;
45
import org.slf4j.Logger;
46
import org.slf4j.LoggerFactory;
47

    
48
public class FeatureTextUtils {
49
        
50
        private static final Logger logger = LoggerFactory.getLogger(FeatureTextUtils.class);
51
        
52
        /**
53
         * The format of the clipboard content will be:
54
         * 
55
         * <FEATURE><CLIPBOARD_SEPARATOR_1><FEATURE><CLIPBOARD_SEPARATOR_1><FEATURE>...
56
         * 
57
         * <FEATURE> = <WKT><CLIPBOARD_SEPARATOR_2><FIELD><CLIPBOARD_SEPARATOR_2><FIELD>...
58
         * 
59
         * <FIELD> = <NAME><CLIPBOARD_SEPARATOR_3><TYPE><CLIPBOARD_SEPARATOR_3><VALUE>
60
         * 
61
         *  Fields are optional, so a WKT string alone will also be valid.
62
         */
63
        public static final String CLIPBOARD_SEPARATOR_1 = "_GVSIGCOPYPASTESEPARATOR1_";
64
        public static final String CLIPBOARD_SEPARATOR_2 = "_GVSIGCOPYPASTESEPARATOR2_";
65
        public static final String CLIPBOARD_SEPARATOR_3 = "_GVSIGCOPYPASTESEPARATOR3_";
66
        
67
        private static GeometryManager gm = null;
68
        private static GeometryOperationContext wktctxt = new GeometryOperationContext(); 
69
        
70
        
71
        public static GeometryManager geoman() {
72
                if (gm == null) {
73
                        gm = GeometryLocator.getGeometryManager();
74
                }
75
                return gm;
76
        }
77
        
78
        public static boolean clipboardSeemsToHaveValidFeatures() {
79
                
80
                if (!textInClipboard()) {
81
                        return false;
82
                }
83
                
84
                String clipb = PluginServices.getFromClipboard();
85
                
86
                if (clipb == null || clipb.length() < 5) {
87
                        return false;
88
                }
89
                
90
                String[] feats = clipb.split(CLIPBOARD_SEPARATOR_1);
91
                String[] feat_parts = feats[0].split(CLIPBOARD_SEPARATOR_2);
92
                
93
                if (feat_parts[0].length() > 10000) {
94
                        logger.info("Clipboard: First part (wkt) of feature description is long ("
95
                                        + feat_parts[0].length() +
96
                                        "). Not parsed. Returned 'true' meaning 'perhaps'.");
97
                        /*
98
                         * 10000 characters is about 400 vertices or more.
99
                         * This seems to be a large geometry and we are not
100
                         * going to parse it here because this method must be fast.
101
                         * We will say "true" so the user will try to paste it, and perhaps it will
102
                         * not work (a dialog message will show, for example)
103
                         */
104
                        return true;
105
                }
106
                
107
                Object geom_obj = null;
108
                
109
                try {
110
                        geom_obj = geoman().createFrom(feat_parts[0]);
111
                } catch (Exception e) {
112
                        logger.info("Unable to parse short WKT: " + e.getMessage());
113
                        /*
114
                         * We discard the content of the clipboard after trying to parse only the
115
                         * first geometry (perhaps there were other geometries, but this method
116
                         * has to be very fast)
117
                         */
118
                        return false;
119
                }
120
                
121
                return geom_obj instanceof Geometry;
122
        }
123
        
124
        public static boolean textInClipboard() {
125
                
126
                return Toolkit.getDefaultToolkit().getSystemClipboard(
127
                                ).isDataFlavorAvailable(DataFlavor.stringFlavor);
128
        }
129

    
130
        public static StringBuilder toString(
131
                        FeatureSet fset,
132
                        FeatureType fty,
133
                        boolean include_atts) throws DataException {
134
                
135
                StringBuilder strb = new StringBuilder();
136
                Feature feat = null;
137
                DisposableIterator diter = fset.fastIterator();
138
                while (diter.hasNext()) {
139
                        feat = (Feature) diter.next();
140
                        if (strb.length() > 0) {
141
                                strb.append(CLIPBOARD_SEPARATOR_1);
142
                        }
143
                        try {
144
                                appendFeatureText(strb, feat, fty, include_atts);
145
                        } catch (Exception e) {
146
                                logger.info("One of the features in clipboard was not valid.", e);
147
                        }
148
                }
149
                diter.dispose();
150
                return strb;
151
        }
152
        
153
        private static void appendFeatureText(
154
                        StringBuilder strb,
155
                        Feature feat,
156
                        FeatureType fty,
157
                        boolean include_atts) throws Exception {
158

    
159
                String aux = feat.getDefaultGeometry().convertToWKT();
160
                strb.append(aux);
161
                
162
                if (!include_atts) {
163
                        return;
164
                }
165
                
166
                FeatureAttributeDescriptor[] atts = fty.getAttributeDescriptors();
167
                for (int i=0; i<atts.length; i++) {
168
                        if (atts[i].getType() != DataTypes.GEOMETRY) {
169
                                strb.append(CLIPBOARD_SEPARATOR_2);
170
                                appendAttribute(strb, feat, atts[i].getName(), atts[i].getType());
171
                        }
172
                }
173
                
174
        }
175

    
176
        private static void appendAttribute(
177
                        StringBuilder strb,
178
                        Feature feat,
179
                        String name,
180
                        int type) {
181
                
182
                strb.append(name);
183
                strb.append(CLIPBOARD_SEPARATOR_3);
184
                strb.append(type);
185
                strb.append(CLIPBOARD_SEPARATOR_3);
186
                strb.append(feat.get(name).toString());
187
        }
188

    
189
        public static List<EditableFeature> fromString(String str, FeatureStore fsto) {
190
                
191
                List<EditableFeature> resp = new ArrayList<EditableFeature>();
192
                
193
                if (!textInClipboard()) {
194
                        return resp;
195
                }
196

    
197
                if (str == null || str.length() < 5) {
198
                        return resp;
199
                }
200
                
201
                String[] feats = str.split(CLIPBOARD_SEPARATOR_1);
202
                EditableFeature item = null;
203
                
204
                for (int i=0; i<feats.length; i++) {
205
                        item = stringToFeature(feats[i], fsto);
206
                        if (item != null) {
207
                                resp.add(item);
208
                        }
209
                }
210
                return resp;
211
        }
212

    
213
        /**
214
         * Returns null if feature was not created
215
         * 
216
         * @param str
217
         * @param fsto
218
         * @return
219
         */
220
        private static EditableFeature stringToFeature(String str, FeatureStore fsto) {
221
                
222
                String[] feat_parts = str.split(CLIPBOARD_SEPARATOR_2);
223
                Object geom_obj = null;
224
                try {
225
                        geom_obj = geoman().createFrom(feat_parts[0]);
226
                } catch (Exception e) {
227
                        logger.info("Unable to parse WKT: " + e.getMessage());
228
                        return null;
229
                }
230
                
231
                if (!(geom_obj instanceof Geometry)) {
232
                        // Parse issue, no feature
233
                        return null;
234
                }
235
                
236
                EditableFeature resp = null;
237
                try {
238
                        resp = fsto.createNewFeature(true);
239
                } catch (DataException e) {
240
                        logger.error("Unable to create feature in clipboard operation.", e);
241
                        return null;
242
                }
243
                
244
                // set geometry
245
                resp.setDefaultGeometry((Geometry) geom_obj);
246
                for (int i=1; i<feat_parts.length; i++) {
247
                        setAttribute(resp, feat_parts[i]);
248
                }
249
                return resp;
250
        }
251

    
252
        private static void setAttribute(EditableFeature resp, String att_desc) {
253
                
254
                String[] att_parts = att_desc.split(CLIPBOARD_SEPARATOR_3);
255
                if (att_parts.length != 3) {
256
                        // must be: name - type - value
257
                        return;
258
                }
259
                
260
                FeatureType fty = null;
261
                fty = resp.getType();
262
                
263
                if (fty.get(att_parts[0]) == null) {
264
                        // name not in feature type
265
                        return;
266
                }
267
                
268
                try {
269
                        resp.set(att_parts[0], att_parts[2]);
270
                } catch (Exception ex) {
271
                        /*
272
                        logger.info("Did not set value for field '" + att_parts[0]
273
                                        + "': " + ex.getMessage());
274
                        */
275
                }
276
        }
277
        
278
        
279
        
280
        
281

    
282
}