Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.file / org.gvsig.fmap.dal.file.csv / src / main / java / org / gvsig / fmap / dal / store / csv / xml / GfsFile.java @ 47634

History | View | Annotate | Download (21.9 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.fmap.dal.store.csv.xml;
7

    
8
import java.io.BufferedWriter;
9
import java.io.File;
10
import java.io.FileWriter;
11
import java.io.IOException;
12
import java.util.ArrayList;
13
import java.util.Arrays;
14
import java.util.Iterator;
15
import java.util.List;
16
import java.util.Locale;
17
import java.util.Map;
18
import javax.xml.parsers.SAXParser;
19
import javax.xml.parsers.SAXParserFactory;
20
import org.apache.commons.collections4.map.LinkedMap;
21
import org.apache.commons.io.FilenameUtils;
22
import org.apache.commons.io.IOUtils;
23
import org.apache.commons.lang3.StringUtils;
24
import org.gvsig.fmap.dal.store.csv.xml.GfsFile.PropertyDefn;
25
import org.gvsig.fmap.dal.store.csv.xml.xmlinfo.XMLAttributeInfoImpl;
26
import org.gvsig.fmap.dal.store.csv.xml.xmlinfo.XMLInfoImpl;
27
import org.gvsig.tools.ToolsLocator;
28
import org.gvsig.tools.dataTypes.DataTypes;
29
import org.gvsig.tools.dataTypes.DataTypesManager;
30
import org.gvsig.tools.library.impl.DefaultLibrariesInitializer;
31
import org.gvsig.tools.task.SimpleTaskStatus;
32
import org.gvsig.tools.util.IsEmpty;
33
import org.gvsig.tools.util.Size;
34
import org.slf4j.Logger;
35
import org.slf4j.LoggerFactory;
36
import org.xml.sax.Attributes;
37
import org.xml.sax.InputSource;
38
import org.xml.sax.Locator;
39
import org.xml.sax.SAXException;
40
import org.xml.sax.helpers.DefaultHandler;
41

    
42
/**
43
 *
44
 * @author fdiaz
45
 */
46
public class GfsFile implements Iterable<PropertyDefn>, IsEmpty, Size {
47

    
48
    private static final Logger LOGGER = LoggerFactory.getLogger(GfsFile.class);
49

    
50
    private static final String PROPERTY_NAME_SEPARATOR = "_";
51
    private static final String PROPERTY_PATH_SEPARATOR = "|";
52
    private static final String PROPERTY_ATTRIBUTE_SEPARATOR = "@";
53

    
54
    public static class PropertyDefn {
55
        private String name;
56
        private String elementPath;
57
        private int type;
58
        private int width;
59
        private boolean isAttr;
60

    
61
        public PropertyDefn() {
62
        }
63
        
64
        public PropertyDefn(String name, String elementPath, int type, int width, boolean isAttr) {
65
            this.name = name;
66
            this.elementPath = elementPath;
67
            this.type = type;
68
            this.width = width;
69
            this.isAttr = isAttr;
70
        }
71

    
72
        public String getName() {
73
            return name;
74
        }
75

    
76
        public void setName(String name) {
77
            this.name = name;
78
        }
79

    
80
        public String getElementPath() {
81
            return elementPath;
82
        }
83
        
84
        public void setElementPath(String elementPath) {
85
            this.elementPath = elementPath;
86
        }
87

    
88
        public int getType() {
89
            return type;
90
        }
91

    
92
        public void setType(int type) {
93
            this.type = type;
94
        }
95

    
96
        public int getWidth() {
97
            return width;
98
        }
99

    
100
        public void setWidth(int width) {
101
            this.width = width;
102
        }
103

    
104
        public boolean isAttr() {
105
            return isAttr;
106
        }
107
        
108
        public void setIsAttr(boolean b) {
109
            this.isAttr = b;
110
        }
111

    
112
        @Override
113
        public boolean equals(Object obj) {
114
            if(!(obj instanceof PropertyDefn)) {
115
                return false;
116
            }
117
            PropertyDefn other = (PropertyDefn)obj;
118
            if(!StringUtils.equals(this.getName(), other.getName())){
119
                return false;
120
            }
121
            if(!StringUtils.equals(this.getElementPath(), other.getElementPath())){
122
                return false;
123
            }
124
            if(this.getType()!=other.getType()){
125
                return false;
126
            }
127
            if(this.getWidth()!=other.getWidth()){
128
                return false;
129
            }
130
            if(this.isAttr()!=other.isAttr()){
131
                return false;
132
            }
133
            return true;
134
        }
135
    }
136
    
137
    private String name;
138
    private List<String> geometryElementPaths;
139
    private String baseElementPath;
140
    private Map<String, PropertyDefn> properties;
141
    private int gmlVersion;
142

    
143
    public String getName() {
144
        return name;
145
    }
146

    
147
    public void setName(String name) {
148
        this.name = name;
149
    }
150

    
151
    public List<String> getGeometryElementPaths() {
152
        return geometryElementPaths;
153
    }
154

    
155
    public void setGeometryElementPaths(List<String> geometryElementPaths) {
156
        this.geometryElementPaths = geometryElementPaths;
157
    }
158

    
159
    public void addGeometryElementPath(String geometryElementPath) {
160
        if(StringUtils.isBlank(geometryElementPath)){
161
            return;
162
        }
163
        if(this.geometryElementPaths == null){
164
            this.geometryElementPaths = new ArrayList<>();
165
        }
166
        this.geometryElementPaths.add(geometryElementPath);
167
    }
168

    
169
    public String getBaseElementPath() {
170
        return baseElementPath;
171
    }
172

    
173
    public void setBaseElementPath(String baseElementPath) {
174
        this.baseElementPath = baseElementPath;
175
    }
176
    
177
    private String findBaseElementPath(XMLInfoImpl xmlinfo) {
178
        String possibleMemberPath = null;
179
        for (String path : xmlinfo.getTagsPaths()) {
180
            XMLAttributeInfoImpl tag = xmlinfo.getTag(path);
181
            
182
            if (StringUtils.isBlank(possibleMemberPath)
183
                    && !tag.isAttr() 
184
                    && !StringUtils.equalsIgnoreCase(tag.getNs(), "gml")
185
                    && !StringUtils.equalsIgnoreCase(path, "FeatureCollection/boundedBy")
186
                    ) {
187
                
188
                String[] ss = path.split("/");
189
                if(ss.length == 2){
190
                    possibleMemberPath = path;
191
                }
192
            }
193
            if (path.equalsIgnoreCase("FeatureCollection/member")) {
194
                return path;
195
            } else if (path.equalsIgnoreCase("FeatureCollection/featureMember")) {
196
                return path;
197
            }
198
        }
199
        return possibleMemberPath;
200
    }
201

    
202
    private List<String> findGeometryElementPaths(XMLInfoImpl xmlinfo) {
203
        List<String> result = new ArrayList<>();
204
        List<String> paths = new ArrayList<>();
205
        for (String path : xmlinfo.getTagsPaths()) {
206
            XMLAttributeInfoImpl tag = xmlinfo.getTag(path);
207
            if(tag.isAttr()){
208
                continue;
209
            }
210
            paths.add(path);
211
        }
212
        for (int i = 0; i < paths.size(); i++) {
213
            String path = paths.get(i);
214
            XMLAttributeInfoImpl tag = xmlinfo.getTag(path);
215
            if(i == paths.size()-1){
216
                continue;
217
            }
218
            XMLAttributeInfoImpl nextTag = xmlinfo.getTag(paths.get(i+1));
219

    
220
            String p = null;
221
            
222
            switch(nextTag.getName().toUpperCase()){
223
                case "POINT":
224
                case "MULTIPOINT":
225
                case "LINESTRING":
226
                    p=path;
227
                    this.gmlVersion = 0;
228
                    break;
229

    
230
                case "POLYGON":
231
                case "MULTIPOLYGON":
232
                    p=path;
233
                    this.gmlVersion = 2;
234
                    break;
235
                case "SURFACE":
236
                case "MULTISURFACE":
237
                case "CURVE":
238
                case "MULTICURVE":
239
                    p=path;
240
                    this.gmlVersion = 3;
241
            }
242
            if(p!=null){
243
                for (String s : result) {
244
                    if(StringUtils.startsWithIgnoreCase(p, s)){
245
                        p=null;
246
                        break;
247
                    }
248
                }
249
                if (p != null) {
250
                    result.add(p);
251
                }
252
            }
253
        }
254
        
255
        if(result.isEmpty()){
256
            return null;
257
        }
258
        return result;
259
    }
260

    
261

    
262
    
263
    @Override
264
    public String toString() {
265
        try {
266
            DataTypesManager datatypesManager = ToolsLocator.getDataTypesManager();
267
            StringBuilder builder = new StringBuilder();
268
            builder.append("<GMLFeatureClassList>\n"
269
                    + "  <GMLFeatureClass>\n"
270
                    + "    <Name>"+getName()+"</Name>\n"
271
                    + "    <ElementPath>"+getBaseElementPath()+"</ElementPath>\n"
272
            );
273
            for (String geometryElementPath : getGeometryElementPaths()) {
274
                builder.append("    <GeometryElementPath>"+geometryElementPath+"</GeometryElementPath>\n");
275
            }
276
            for (PropertyDefn property : properties.values()) {
277
                int type = property.getType();
278
                String propertyType = datatypesManager.getTypeName(type);
279

    
280
                builder.append("    <PropertyDefn>\n");
281
                builder.append("      <Name>");
282
                builder.append(property.getName());
283
                builder.append( "</Name>\n");
284

    
285
                builder.append("      <ElementPath>");
286
                builder.append(property.getElementPath());
287
                
288
                if (property.isAttr()) {
289
                    //cambiamos el ?ltimo | por @
290
                    int lastIndex = builder.lastIndexOf(PROPERTY_PATH_SEPARATOR);
291
                    builder.replace(lastIndex, PROPERTY_PATH_SEPARATOR.length() + lastIndex, PROPERTY_ATTRIBUTE_SEPARATOR);
292
                }
293

    
294
                builder.append("</ElementPath>\n");
295
                builder.append("      <Type>");
296
                builder.append(propertyType);
297
                builder.append("</Type>\n");
298
                if(type == DataTypes.STRING){
299
                    builder.append("      <Width>");
300
                    builder.append(property.getWidth());
301
                    builder.append("</Width>\n");
302
                }
303
                builder.append("    </PropertyDefn>\n");
304

    
305
            }
306

    
307
            builder.append("  </GMLFeatureClass>\n"
308
                    + "</GMLFeatureClassList>");
309
            
310
            return builder.toString();
311
        } catch (Exception ex) {
312
            LOGGER.warn("Can't generate gfs file", ex);
313
            return null;
314
        }
315
    }
316
    
317
    private void removeBaseInGeometryPaths() {
318
        if(geometryElementPaths == null){
319
            return;
320
        }
321
        List<String> l = new ArrayList<>();
322
        for (String geometryElementPath : geometryElementPaths) {
323
            if (geometryElementPath.startsWith(baseElementPath + "/")) {
324
                geometryElementPath = geometryElementPath.substring(baseElementPath.length() + 1);
325
            }
326
            l.add(geometryElementPath);
327
        }
328
        this.geometryElementPaths = l;
329
    }
330
    
331
    public void fetch(File gmlFile) {
332
        this.properties = new LinkedMap<>();
333
        SimpleTaskStatus status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("GML");
334
        status.setAutoremove(true);
335
        try {
336
            status.add();
337
            StructureExtractorImpl extractor = new StructureExtractorImpl();
338
             //Ojo con defaultCharset
339
            XMLInfoImpl xmlinfo = extractor.extractStructure(gmlFile, null, Locale.getDefault(), status);
340
            
341
            
342
            this.name = FilenameUtils.getBaseName(gmlFile.getName());
343
            
344
            this.baseElementPath = findBaseElementPath(xmlinfo);
345
            this.geometryElementPaths = findGeometryElementPaths(xmlinfo);
346
            
347
            removeBaseInGeometryPaths();
348

    
349
            for (String path : xmlinfo.getTagsPaths()) {
350
                XMLAttributeInfoImpl tag = xmlinfo.getTag(path);
351
                if (tag.hasChilds()) {
352
                    continue;
353
                }
354
                if (path.startsWith(baseElementPath+"/")) {
355
                    path = path.substring(baseElementPath.length()+1);
356
                } else {
357
                    continue;
358
                }
359
                boolean found = false;
360
                if(geometryElementPaths != null){
361
                    for (String geometryElementPath : geometryElementPaths) {
362
                        if (path.equals(geometryElementPath)) {
363
                            found = true;
364
                            break;
365
                        }
366
                        if (path.startsWith(geometryElementPath+"/")) {
367
                            if(tag.getNs().equalsIgnoreCase("gml")){
368
                                found = true;
369
                                break;
370
                            }
371
                        }
372
                    }
373
                    if(found){
374
                        continue;
375
                    }
376
                }
377
                if(path.indexOf('/') < 0 && tag.isAttr()){
378
                    continue;
379
                }
380

    
381
                String[] path_ss = path.split("/");
382
                String lastName = path_ss[path_ss.length -1];
383
                String propertyName = StringUtils.replace(path, "/", PROPERTY_NAME_SEPARATOR);
384
                if(StringUtils.endsWith(path, "$v")){
385
                    propertyName = StringUtils.replace(propertyName, PROPERTY_NAME_SEPARATOR+lastName+"$v", "");
386
                }
387
                String propertyPath = StringUtils.replace(path, "/", PROPERTY_PATH_SEPARATOR);
388
                if(StringUtils.endsWith(path, "$v")){
389
                    propertyPath = StringUtils.replace(propertyPath, PROPERTY_PATH_SEPARATOR+lastName+"$v", "");
390
                }
391
                propertyPath = StringUtils.replace(propertyPath, "$v", "");
392
                this.properties.put(propertyName, new PropertyDefn(propertyName, propertyPath, tag.getType(), tag.getSize(), tag.isAttr()));
393

    
394
            }
395

    
396
            status.terminate();
397
        } catch (Exception ex) {
398
            LOGGER.warn("Can't generate gfs file", ex);
399
            status.abort();
400
            throw new RuntimeException("", ex);
401
        }
402
        
403
    }
404
    
405
    public void load(File gfsFile) {
406
        SimpleTaskStatus status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("GML");
407
        status.setAutoremove(true);
408
        
409
        this.setName(null);
410
        this.setBaseElementPath(null);
411
        this.setGeometryElementPaths(null);
412
        this.properties = new LinkedMap<>();
413
        
414
        
415
        try {
416
            status.add();
417
            
418
            InputSource is = XmlCommons.openReader(gfsFile,null);
419
            SAXParserFactory spf = SAXParserFactory.newInstance();
420
            spf.setNamespaceAware(true);
421
            List<String> path = new ArrayList<>();
422
            DataTypesManager dataTypesManager = ToolsLocator.getDataTypesManager();
423
            
424
            SAXParser saxParser = spf.newSAXParser();
425
            saxParser.parse(gfsFile, new DefaultHandler() {
426
                private Locator locator;
427
                int refreshInterval = 1;
428
                StringBuilder chars = new StringBuilder();
429
                PropertyDefn property = null;
430
                
431
//                boolean readingProperty = false;
432
//                String propertyName = null;
433
//                String propertyElementPath = null;
434
//                Integer propertyType = null;
435
//                Integer propertyWidth = null;
436

    
437
                @Override
438
                public void setDocumentLocator(Locator locator) {
439
                    this.locator = locator;
440
                }
441

    
442
                @Override
443
                public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
444
                    int line = this.locator.getLineNumber();
445
//                    int column = this.locator.getColumnNumber()-2-localName.length();
446

    
447
                    if(line % refreshInterval == 0) {
448
                        status.setCurValue(line);
449
                    }
450
                    
451
                    if(line > 100000){
452
                        refreshInterval = 10000;
453
                    } else if(line > 10000){
454
                        refreshInterval = 1000;
455
                    } else if(line > 1000){
456
                        refreshInterval = 100;
457
                    } else if(line > 100){
458
                        refreshInterval = 10;
459
                    }
460
                    
461
                    if(StringUtils.equals(localName, "PropertyDefn")){
462
                        property = new PropertyDefn();
463
//                        readingProperty = true;
464
                    }
465

    
466
                    path.add(localName);
467

    
468
                    chars.setLength(0);
469
                    
470
                }
471

    
472
                @Override
473
                public void endElement(String uri, String localName, String qName) throws SAXException {
474
                    if(StringUtils.equals(localName, "PropertyDefn")){
475
                        properties.put(this.property.getName(), property);
476
                        property = null;
477
                    } else if(this.property != null){
478
                        if(StringUtils.equals(localName, "Name")){
479
                            String value = this.chars.toString();
480
                            this.property.setName(value);
481
                        } else if(StringUtils.equals(localName, "ElementPath")){
482
                            String value = this.chars.toString();
483
                            if(value.indexOf(PROPERTY_ATTRIBUTE_SEPARATOR)>=0){
484
                                this.property.setIsAttr(true);
485
                                value = value.replace(PROPERTY_ATTRIBUTE_SEPARATOR, PROPERTY_PATH_SEPARATOR);
486
                            }
487
                            this.property.setElementPath(value);
488
                        } else if(StringUtils.equals(localName, "Type")){
489
                            String value = this.chars.toString();
490
                            this.property.setType(dataTypesManager.getType(value));
491
                        } else if(StringUtils.equals(localName, "Width")){
492
                            int value = Integer.valueOf(this.chars.toString());
493
                            this.property.setWidth(value);
494
                        }
495
                    } else {
496
                        if(StringUtils.equals(localName, "Name")){
497
                            String value = this.chars.toString();
498
                            setName(value);
499
                        } else if(StringUtils.equals(localName, "ElementPath")){
500
                            String value = this.chars.toString();
501
                            setBaseElementPath(value);
502
                        } else if(StringUtils.equals(localName, "GeometryElementPath")){
503
                            String value = this.chars.toString();
504
                            addGeometryElementPath(value);
505
                        }
506
                    }
507

    
508
                    chars.setLength(0);
509
                }
510
                
511
                
512
                @Override
513
                public void characters(char[] ch, int start, int length) throws SAXException {
514
                    this.chars.append(ch, start, length);
515
                }
516

    
517
            }
518
            );
519
            status.terminate();
520

    
521
        } catch (Exception ex) {
522
            status.abort();
523
            throw new RuntimeException("Can't load gfs file '"+gfsFile.getAbsolutePath()+"'", ex);
524
        }
525
    }
526
    
527
    public void save(File gfsFile) throws IOException {
528
        BufferedWriter writer = null;
529
        try {
530
            writer = new BufferedWriter(new FileWriter(gfsFile));
531
            writer.append(this.toString());
532
        } finally {
533
            IOUtils.closeQuietly(writer);
534
        }
535
    }
536
    
537
    @Override
538
    public Iterator<PropertyDefn> iterator() {
539
        return this.properties.values().iterator();
540
    }
541

    
542
    @Override
543
    public boolean isEmpty() {
544
        return this.properties.isEmpty();
545
    }
546

    
547
    @Override
548
    public int size() {
549
        return this.properties.size();
550
    }
551
    
552
    public List<String> getPropertiesPaths() {
553
        List<String> res = new ArrayList<>();
554
        for (PropertyDefn property : this.properties.values()) {
555
            res.add(property.getElementPath().replace(PROPERTY_PATH_SEPARATOR, "/"));
556
        }
557
        return res;
558
    }
559
    
560
    public PropertyDefn get(String propertyName) {
561
        return this.properties.get(propertyName);        
562
    }
563
    
564
    @Override
565
    public boolean equals(Object obj) {
566
        if(!(obj instanceof GfsFile)) {
567
            return false;
568
        }
569
        GfsFile other = (GfsFile)obj;
570
        if(!this.name.equals(other.getName())){
571
            return false;
572
        }
573
        if(!this.baseElementPath.equals(other.getBaseElementPath())){
574
            return false;
575
        }
576
        if(!this.geometryElementPaths.equals(other.getGeometryElementPaths())){
577
            return false;
578
        }
579
        
580
        if(this.size() != other.size()){
581
            return false;
582
        }
583
        for (PropertyDefn property : this) {
584
            PropertyDefn otherProperty = other.get(property.getName());
585
            if(!property.equals(otherProperty)){
586
                System.out.println("MY :"+property.getElementPath());
587
                System.out.println("OT :"+otherProperty.getElementPath());
588
                return false;
589
            }
590
            
591
        }
592
        
593
        return true;
594
    }
595
    
596
    
597
    
598
    public static void main(String[] args) throws Exception {
599
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/1075305YJ2717N.gml";
600
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/Recinto.gml";
601
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/FG-GML-543863-AdmBdry-20190101-0001.gml";
602
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/Municipis.gml";
603
        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/navarra.gml";
604

    
605
        new DefaultLibrariesInitializer().fullInitialize();
606
        
607
        GfsFile gfs = new GfsFile();
608
        gfs.fetch(new File(XMLFILE1));
609
        System.out.println(gfs.toString());
610
        System.out.println(StringUtils.join(gfs.getPropertiesPaths(), "\n"));
611
        File gfsFile = new File(FilenameUtils.removeExtension(XMLFILE1)+".gfs");
612
        gfs.save(gfsFile);
613
        
614
        GfsFile gfs2 = new GfsFile();
615
        gfs2.load(gfsFile);
616
        System.out.println("=========================================");
617
        System.out.println(gfs.toString());
618
        System.out.println(StringUtils.join(gfs.getPropertiesPaths(), "\n"));
619
        System.out.println("Los gfs "+(gfs.equals(gfs2)?"S?":"NO")+" son iguales");
620
    }
621
}