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 / gml / virtualrows / GfsFile.java @ 47646

History | View | Annotate | Download (23.5 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.gml.virtualrows;
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.Iterator;
14
import java.util.List;
15
import java.util.Locale;
16
import java.util.Map;
17
import javax.xml.parsers.SAXParser;
18
import javax.xml.parsers.SAXParserFactory;
19
import org.apache.commons.collections4.map.LinkedMap;
20
import org.apache.commons.io.FilenameUtils;
21
import org.apache.commons.io.IOUtils;
22
import org.apache.commons.lang3.StringUtils;
23
import org.gvsig.fmap.dal.store.gml.virtualrows.GfsFile.PropertyDefn;
24
import org.gvsig.fmap.dal.store.gml.virtualrows.xmlinfo.XMLAttributeInfoImpl;
25
import org.gvsig.fmap.dal.store.gml.virtualrows.xmlinfo.XMLInfoImpl;
26
import org.gvsig.tools.ToolsLocator;
27
import org.gvsig.tools.dataTypes.DataTypes;
28
import org.gvsig.tools.dataTypes.DataTypesManager;
29
import org.gvsig.tools.library.impl.DefaultLibrariesInitializer;
30
import org.gvsig.tools.task.SimpleTaskStatus;
31
import org.gvsig.tools.util.IsEmpty;
32
import org.gvsig.tools.util.Size;
33
import org.slf4j.Logger;
34
import org.slf4j.LoggerFactory;
35
import org.xml.sax.Attributes;
36
import org.xml.sax.InputSource;
37
import org.xml.sax.Locator;
38
import org.xml.sax.SAXException;
39
import org.xml.sax.helpers.DefaultHandler;
40

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
155
    public List<String> getGeometryElementPaths() {
156
        return geometryElementPaths;
157
    }
158

    
159
    public void setGeometryElementPaths(List<String> geometryElementPaths) {
160
        this.geometryElementPaths = geometryElementPaths;
161
    }
162

    
163
    public void addGeometryElementPath(String geometryElementPath) {
164
        if(StringUtils.isBlank(geometryElementPath)){
165
            return;
166
        }
167
        if(this.geometryElementPaths == null){
168
            this.geometryElementPaths = new ArrayList<>();
169
        }
170
        this.geometryElementPaths.add(geometryElementPath);
171
    }
172

    
173
    public void addGeometryElementSrs(String geometryElementSrs) {
174
        if(StringUtils.isBlank(geometryElementSrs)){
175
            return;
176
        }
177
        if(this.geometryElementSrss == null){
178
            this.geometryElementSrss = new ArrayList<>();
179
        }
180
        if(StringUtils.equalsIgnoreCase("null", geometryElementSrs)){
181
            this.geometryElementSrss.add(null);
182
        } else {
183
            this.geometryElementSrss.add(geometryElementSrs);
184
        }
185
    }
186

    
187
    public String getBaseElementPath() {
188
        return baseElementPath;
189
    }
190

    
191
    public void setBaseElementPath(String baseElementPath) {
192
        this.baseElementPath = baseElementPath;
193
    }
194
    
195
    private String findBaseElementPath(XMLInfoImpl xmlinfo) {
196
        String possibleMemberPath = null;
197
        for (String path : xmlinfo.getTagsPaths()) {
198
            XMLAttributeInfoImpl tag = xmlinfo.getTag(path);
199
            
200
            if (StringUtils.isBlank(possibleMemberPath)
201
                    && !tag.isAttr() 
202
                    && !StringUtils.equalsIgnoreCase(tag.getNs(), "gml")
203
                    && !StringUtils.equalsIgnoreCase(path, "FeatureCollection/boundedBy")
204
                    ) {
205
                
206
                String[] ss = path.split("/");
207
                if(ss.length == 2){
208
                    possibleMemberPath = path;
209
                }
210
            }
211
            if (path.equalsIgnoreCase("FeatureCollection/member")) {
212
                return path;
213
            } else if (path.equalsIgnoreCase("FeatureCollection/featureMember")) {
214
                return path;
215
            }
216
        }
217
        return possibleMemberPath;
218
    }
219

    
220
    private List<String> findGeometryElementSrss(XMLInfoImpl xmlinfo, List<String> elementPaths) {
221
        List<String> result = new ArrayList<>();
222
        for (String elementPath : elementPaths) {
223
            XMLAttributeInfoImpl x = xmlinfo.getTag(elementPath);
224
            if(x==null){
225
                result.add(null);
226
            } else {
227
                result.add(x.getSrs());
228
            }
229
        }
230
        return result;
231
    }
232
    
233
    private List<String> findGeometryElementPaths(XMLInfoImpl xmlinfo) {
234
        List<String> result = new ArrayList<>();
235
        List<String> paths = new ArrayList<>();
236
        for (String path : xmlinfo.getTagsPaths()) {
237
            XMLAttributeInfoImpl tag = xmlinfo.getTag(path);
238
            if(tag.isAttr()){
239
                continue;
240
            }
241
            paths.add(path);
242
        }
243
        for (int i = 0; i < paths.size(); i++) {
244
            String path = paths.get(i);
245
            XMLAttributeInfoImpl tag = xmlinfo.getTag(path);
246
            if(i == paths.size()-1){
247
                continue;
248
            }
249
            XMLAttributeInfoImpl nextTag = xmlinfo.getTag(paths.get(i+1));
250

    
251
            String p = null;
252
            
253
            switch(nextTag.getName().toUpperCase()){
254
                case "POINT":
255
                case "MULTIPOINT":
256
                case "LINESTRING":
257
                    p=path;
258
                    this.gmlVersion = 0;
259
                    break;
260

    
261
                case "POLYGON":
262
                case "MULTIPOLYGON":
263
                    p=path;
264
                    this.gmlVersion = 2;
265
                    break;
266
                case "SURFACE":
267
                case "MULTISURFACE":
268
                case "CURVE":
269
                case "MULTICURVE":
270
                    p=path;
271
                    this.gmlVersion = 3;
272
            }
273
            if(p!=null){
274
                for (String s : result) {
275
                    if(StringUtils.startsWithIgnoreCase(p, s)){
276
                        p=null;
277
                        break;
278
                    }
279
                }
280
                if (p != null) {
281
                    result.add(p);
282
//                    tag.setSrs(nextTag.getSrs());
283
                }
284
            }
285
        }
286
        
287
        if(result.isEmpty()){
288
            return null;
289
        }
290
        return result;
291
    }
292

    
293

    
294
    
295
    @Override
296
    public String toString() {
297
        try {
298
            DataTypesManager datatypesManager = ToolsLocator.getDataTypesManager();
299
            StringBuilder builder = new StringBuilder();
300
            builder.append("<GMLFeatureClassList>\n"
301
                    + "  <GMLFeatureClass>\n"
302
                    + "    <Name>"+getName()+"</Name>\n"
303
                    + "    <ElementPath>"+getBaseElementPath()+"</ElementPath>\n"
304
            );
305
            for (String geometryElementPath : getGeometryElementPaths()) {
306
                builder.append("    <GeometryElementPath>"+geometryElementPath+"</GeometryElementPath>\n");
307
            }
308
            for (String geometryElementSrs : getGeometryElementSrss()) {
309
                builder.append("    <GeometryElementSrs>"+geometryElementSrs+"</GeometryElementSrs>\n");
310
            }
311
            for (PropertyDefn property : properties.values()) {
312
                int type = property.getType();
313
                String propertyType = datatypesManager.getTypeName(type);
314

    
315
                builder.append("    <PropertyDefn>\n");
316
                builder.append("      <Name>");
317
                builder.append(property.getName());
318
                builder.append( "</Name>\n");
319

    
320
                builder.append("      <ElementPath>");
321
                builder.append(property.getElementPath());
322
                
323
                if (property.isAttr()) {
324
                    //cambiamos el ?ltimo | por @
325
                    int lastIndex = builder.lastIndexOf(PROPERTY_PATH_SEPARATOR);
326
                    builder.replace(lastIndex, PROPERTY_PATH_SEPARATOR.length() + lastIndex, PROPERTY_ATTRIBUTE_SEPARATOR);
327
                }
328

    
329
                builder.append("</ElementPath>\n");
330
                builder.append("      <Type>");
331
                builder.append(propertyType);
332
                builder.append("</Type>\n");
333
                if(type == DataTypes.STRING){
334
                    builder.append("      <Width>");
335
                    builder.append(property.getWidth());
336
                    builder.append("</Width>\n");
337
                }
338
                builder.append("    </PropertyDefn>\n");
339

    
340
            }
341

    
342
            builder.append("  </GMLFeatureClass>\n"
343
                    + "</GMLFeatureClassList>");
344
            
345
            return builder.toString();
346
        } catch (Exception ex) {
347
            LOGGER.warn("Can't generate gfs file", ex);
348
            return null;
349
        }
350
    }
351
    
352
    private void removeBaseInGeometryPaths() {
353
        if(geometryElementPaths == null){
354
            return;
355
        }
356
        List<String> l = new ArrayList<>();
357
        for (String geometryElementPath : geometryElementPaths) {
358
            if (geometryElementPath.startsWith(baseElementPath + "/")) {
359
                geometryElementPath = geometryElementPath.substring(baseElementPath.length() + 1);
360
            }
361
            l.add(geometryElementPath);
362
        }
363
        this.geometryElementPaths = l;
364
    }
365
    
366
    public void fetch(File gmlFile) {
367
        this.properties = new LinkedMap<>();
368
        SimpleTaskStatus status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("GML");
369
        status.setAutoremove(true);
370
        try {
371
            status.add();
372
            StructureExtractorImpl extractor = new StructureExtractorImpl();
373
             //Ojo con defaultCharset
374
            XMLInfoImpl xmlinfo = extractor.extractStructure(gmlFile, null, Locale.getDefault(), status);
375
            
376
            
377
            this.name = FilenameUtils.getBaseName(gmlFile.getName());
378
            
379
            this.baseElementPath = findBaseElementPath(xmlinfo);
380
            this.geometryElementPaths = findGeometryElementPaths(xmlinfo);
381
            this.geometryElementSrss = findGeometryElementSrss(xmlinfo,this.geometryElementPaths);
382
            
383
            removeBaseInGeometryPaths();
384

    
385
            for (String path : xmlinfo.getTagsPaths()) {
386
                XMLAttributeInfoImpl tag = xmlinfo.getTag(path);
387
                if (tag.hasChilds()) {
388
                    continue;
389
                }
390
                if (path.startsWith(baseElementPath+"/")) {
391
                    path = path.substring(baseElementPath.length()+1);
392
                } else {
393
                    continue;
394
                }
395
                boolean found = false;
396
                if(geometryElementPaths != null){
397
                    for (String geometryElementPath : geometryElementPaths) {
398
                        if (path.equals(geometryElementPath)) {
399
                            found = true;
400
                            break;
401
                        }
402
                        if (path.startsWith(geometryElementPath+"/")) {
403
                            if(tag.getNs().equalsIgnoreCase("gml")){
404
                                found = true;
405
                                break;
406
                            }
407
                        }
408
                    }
409
                    if(found){
410
                        continue;
411
                    }
412
                }
413
                if(path.indexOf('/') < 0 && tag.isAttr()){
414
                    continue;
415
                }
416

    
417
                String[] path_ss = path.split("/");
418
                String lastName = path_ss[path_ss.length -1];
419
                String propertyName = StringUtils.replace(path, "/", PROPERTY_NAME_SEPARATOR);
420
                if(StringUtils.endsWith(path, "$v")){
421
                    propertyName = StringUtils.replace(propertyName, PROPERTY_NAME_SEPARATOR+lastName+"$v", "");
422
                }
423
                String propertyPath = StringUtils.replace(path, "/", PROPERTY_PATH_SEPARATOR);
424
                if(StringUtils.endsWith(path, "$v")){
425
                    propertyPath = StringUtils.replace(propertyPath, PROPERTY_PATH_SEPARATOR+lastName+"$v", "");
426
                }
427
                propertyPath = StringUtils.replace(propertyPath, "$v", "");
428
                this.properties.put(propertyName, new PropertyDefn(propertyName, propertyPath, tag.getType(), tag.getSize(), tag.isAttr()));
429

    
430
            }
431

    
432
            status.terminate();
433
        } catch (Exception ex) {
434
            LOGGER.warn("Can't generate gfs file", ex);
435
            status.abort();
436
            throw new RuntimeException("", ex);
437
        }
438
        
439
    }
440
    
441
    public void load(File gfsFile) {
442
        SimpleTaskStatus status = ToolsLocator.getTaskStatusManager().createDefaultSimpleTaskStatus("GML");
443
        status.setAutoremove(true);
444
        
445
        this.setName(null);
446
        this.setBaseElementPath(null);
447
        this.setGeometryElementPaths(null);
448
        this.properties = new LinkedMap<>();
449
        
450
        
451
        try {
452
            status.add();
453
            
454
            InputSource is = XmlCommons.openReader(gfsFile,null);
455
            SAXParserFactory spf = SAXParserFactory.newInstance();
456
            spf.setNamespaceAware(true);
457
            List<String> path = new ArrayList<>();
458
            DataTypesManager dataTypesManager = ToolsLocator.getDataTypesManager();
459
            
460
            SAXParser saxParser = spf.newSAXParser();
461
            saxParser.parse(gfsFile, new DefaultHandler() {
462
                private Locator locator;
463
                int refreshInterval = 1;
464
                StringBuilder chars = new StringBuilder();
465
                PropertyDefn property = null;
466
                
467
//                boolean readingProperty = false;
468
//                String propertyName = null;
469
//                String propertyElementPath = null;
470
//                Integer propertyType = null;
471
//                Integer propertyWidth = null;
472

    
473
                @Override
474
                public void setDocumentLocator(Locator locator) {
475
                    this.locator = locator;
476
                }
477

    
478
                @Override
479
                public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
480
                    int line = this.locator.getLineNumber();
481
//                    int column = this.locator.getColumnNumber()-2-localName.length();
482

    
483
                    if(line % refreshInterval == 0) {
484
                        status.setCurValue(line);
485
                    }
486
                    
487
                    if(line > 100000){
488
                        refreshInterval = 10000;
489
                    } else if(line > 10000){
490
                        refreshInterval = 1000;
491
                    } else if(line > 1000){
492
                        refreshInterval = 100;
493
                    } else if(line > 100){
494
                        refreshInterval = 10;
495
                    }
496
                    
497
                    if(StringUtils.equals(localName, "PropertyDefn")){
498
                        property = new PropertyDefn();
499
//                        readingProperty = true;
500
                    }
501

    
502
                    path.add(localName);
503

    
504
                    chars.setLength(0);
505
                    
506
                }
507

    
508
                @Override
509
                public void endElement(String uri, String localName, String qName) throws SAXException {
510
                    if(StringUtils.equals(localName, "PropertyDefn")){
511
                        properties.put(this.property.getName(), property);
512
                        property = null;
513
                    } else if(this.property != null){
514
                        if(StringUtils.equals(localName, "Name")){
515
                            String value = this.chars.toString();
516
                            this.property.setName(value);
517
                        } else if(StringUtils.equals(localName, "ElementPath")){
518
                            String value = this.chars.toString();
519
                            if(value.indexOf(PROPERTY_ATTRIBUTE_SEPARATOR)>=0){
520
                                this.property.setIsAttr(true);
521
                                value = value.replace(PROPERTY_ATTRIBUTE_SEPARATOR, PROPERTY_PATH_SEPARATOR);
522
                            }
523
                            this.property.setElementPath(value);
524
                        } else if(StringUtils.equals(localName, "Type")){
525
                            String value = this.chars.toString();
526
                            this.property.setType(dataTypesManager.getType(value));
527
                        } else if(StringUtils.equals(localName, "Width")){
528
                            int value = Integer.valueOf(this.chars.toString());
529
                            this.property.setWidth(value);
530
                        }
531
                    } else {
532
                        if(StringUtils.equals(localName, "Name")){
533
                            String value = this.chars.toString();
534
                            setName(value);
535
                        } else if(StringUtils.equals(localName, "ElementPath")){
536
                            String value = this.chars.toString();
537
                            setBaseElementPath(value);
538
                        } else if(StringUtils.equals(localName, "GeometryElementPath")){
539
                            String value = this.chars.toString();
540
                            addGeometryElementPath(value);
541
                        } else if(StringUtils.equals(localName, "GeometryElementSrs")){
542
                            String value = this.chars.toString();
543
                            addGeometryElementSrs(value);
544
                        }
545
                    }
546

    
547
                    chars.setLength(0);
548
                }
549
                
550
                
551
                @Override
552
                public void characters(char[] ch, int start, int length) throws SAXException {
553
                    this.chars.append(ch, start, length);
554
                }
555

    
556
            }
557
            );
558
            status.terminate();
559

    
560
        } catch (Exception ex) {
561
            status.abort();
562
            throw new RuntimeException("Can't load gfs file '"+gfsFile.getAbsolutePath()+"'", ex);
563
        }
564
    }
565
    
566
    public void save(File gfsFile) throws IOException {
567
        BufferedWriter writer = null;
568
        try {
569
            writer = new BufferedWriter(new FileWriter(gfsFile));
570
            writer.append(this.toString());
571
        } finally {
572
            IOUtils.closeQuietly(writer);
573
        }
574
    }
575
    
576
    @Override
577
    public Iterator<PropertyDefn> iterator() {
578
        return this.properties.values().iterator();
579
    }
580

    
581
    @Override
582
    public boolean isEmpty() {
583
        return this.properties.isEmpty();
584
    }
585

    
586
    @Override
587
    public int size() {
588
        return this.properties.size();
589
    }
590
    
591
    public List<String> getPropertiesPaths() {
592
        List<String> res = new ArrayList<>();
593
        for (PropertyDefn property : this.properties.values()) {
594
            res.add(property.getElementPath().replace(PROPERTY_PATH_SEPARATOR, "/"));
595
        }
596
        return res;
597
    }
598
    
599
    public PropertyDefn get(String propertyName) {
600
        return this.properties.get(propertyName);        
601
    }
602
    
603
    @Override
604
    public boolean equals(Object obj) {
605
        if(!(obj instanceof GfsFile)) {
606
            return false;
607
        }
608
        GfsFile other = (GfsFile)obj;
609
        if(!this.name.equals(other.getName())){
610
            return false;
611
        }
612
        if(!this.baseElementPath.equals(other.getBaseElementPath())){
613
            return false;
614
        }
615
        if(!this.geometryElementPaths.equals(other.getGeometryElementPaths())){
616
            return false;
617
        }
618
        
619
        if(this.size() != other.size()){
620
            return false;
621
        }
622
        for (PropertyDefn property : this) {
623
            PropertyDefn otherProperty = other.get(property.getName());
624
            if(!property.equals(otherProperty)){
625
                System.out.println("MY :"+property.getElementPath());
626
                System.out.println("OT :"+otherProperty.getElementPath());
627
                return false;
628
            }
629
            
630
        }
631
        
632
        return true;
633
    }
634
    
635
    
636
    
637
    public static void main(String[] args) throws Exception {
638
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/1075305YJ2717N.gml";
639
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/Recinto.gml";
640
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/FG-GML-543863-AdmBdry-20190101-0001.gml";
641
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/Municipis.gml";
642
        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/navarra.gml";
643

    
644
        new DefaultLibrariesInitializer().fullInitialize();
645
        
646
        GfsFile gfs = new GfsFile();
647
        gfs.fetch(new File(XMLFILE1));
648
        System.out.println(gfs.toString());
649
        System.out.println(StringUtils.join(gfs.getPropertiesPaths(), "\n"));
650
        File gfsFile = new File(FilenameUtils.removeExtension(XMLFILE1)+".gfs");
651
        gfs.save(gfsFile);
652
        
653
        GfsFile gfs2 = new GfsFile();
654
        gfs2.load(gfsFile);
655
        System.out.println("=========================================");
656
        System.out.println(gfs.toString());
657
        System.out.println(StringUtils.join(gfs.getPropertiesPaths(), "\n"));
658
        System.out.println("Los gfs "+(gfs.equals(gfs2)?"S?":"NO")+" son iguales");
659
    }
660
}