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.gml / src / main / java / org / gvsig / fmap / dal / store / gml / virtualrows / GfsFile.java @ 47664

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

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

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

    
295

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

    
323
                builder.append("    <PropertyDefn>\n");
324
                builder.append("      <Name>");
325
                builder.append(property.getName());
326
                builder.append( "</Name>\n");
327

    
328
                builder.append("      <ElementPath>");
329
                builder.append(property.getElementPath());
330
                
331
                if (property.isAttr()) {
332
                    //cambiamos el ?ltimo | por @
333
                    int lastIndex = builder.lastIndexOf(PROPERTY_PATH_SEPARATOR);
334
                    builder.replace(lastIndex, PROPERTY_PATH_SEPARATOR.length() + lastIndex, PROPERTY_ATTRIBUTE_SEPARATOR);
335
                }
336

    
337
                builder.append("</ElementPath>\n");
338
                builder.append("      <Type>");
339
                builder.append(propertyType);
340
                builder.append("</Type>\n");
341
                if(type == DataTypes.STRING){
342
                    builder.append("      <Width>");
343
                    builder.append(property.getWidth());
344
                    builder.append("</Width>\n");
345
                }
346
                builder.append("    </PropertyDefn>\n");
347

    
348
            }
349

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

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

    
425
                String[] path_ss = path.split("/");
426
                String lastName = path_ss[path_ss.length -1];
427
                String propertyName = StringUtils.replace(path, "/", PROPERTY_NAME_SEPARATOR);
428
                if(StringUtils.endsWith(path, "$v")){
429
                    propertyName = StringUtils.replace(propertyName, PROPERTY_NAME_SEPARATOR+lastName+"$v", "");
430
                }
431
                String propertyPath = StringUtils.replace(path, "/", PROPERTY_PATH_SEPARATOR);
432
                if(StringUtils.endsWith(path, "$v")){
433
                    propertyPath = StringUtils.replace(propertyPath, PROPERTY_PATH_SEPARATOR+lastName+"$v", "");
434
                }
435
                propertyPath = StringUtils.replace(propertyPath, "$v", "");
436
                this.properties.put(propertyName, new PropertyDefn(propertyName, propertyPath, tag.getType(), tag.getSize(), tag.isAttr()));
437

    
438
            }
439

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

    
481
                @Override
482
                public void setDocumentLocator(Locator locator) {
483
                    this.locator = locator;
484
                }
485

    
486
                @Override
487
                public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
488
                    int line = this.locator.getLineNumber();
489
//                    int column = this.locator.getColumnNumber()-2-localName.length();
490

    
491
                    if(line % refreshInterval == 0) {
492
                        status.setCurValue(line);
493
                    }
494
                    
495
                    if(line > 100000){
496
                        refreshInterval = 10000;
497
                    } else if(line > 10000){
498
                        refreshInterval = 1000;
499
                    } else if(line > 1000){
500
                        refreshInterval = 100;
501
                    } else if(line > 100){
502
                        refreshInterval = 10;
503
                    }
504
                    
505
                    if(StringUtils.equals(localName, "PropertyDefn")){
506
                        property = new PropertyDefn();
507
//                        readingProperty = true;
508
                    }
509

    
510
                    path.add(localName);
511

    
512
                    chars.setLength(0);
513
                    
514
                }
515

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

    
555
                    chars.setLength(0);
556
                }
557
                
558
                
559
                @Override
560
                public void characters(char[] ch, int start, int length) throws SAXException {
561
                    this.chars.append(ch, start, length);
562
                }
563

    
564
            }
565
            );
566
            status.terminate();
567

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

    
589
    @Override
590
    public boolean isEmpty() {
591
        return this.properties.isEmpty();
592
    }
593

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

    
652
        new DefaultLibrariesInitializer().fullInitialize();
653
        
654
        GfsFile gfs = new GfsFile();
655
        gfs.fetch(new File(XMLFILE1));
656
        System.out.println(gfs.toString());
657
        System.out.println(StringUtils.join(gfs.getPropertiesPaths(), "\n"));
658
        File gfsFile = new File(FilenameUtils.removeExtension(XMLFILE1)+".gfs");
659
        gfs.save(gfsFile);
660
        
661
        GfsFile gfs2 = new GfsFile();
662
        gfs2.load(gfsFile);
663
        System.out.println("=========================================");
664
        System.out.println(gfs.toString());
665
        System.out.println(StringUtils.join(gfs.getPropertiesPaths(), "\n"));
666
        System.out.println("Los gfs "+(gfs.equals(gfs2)?"S?":"NO")+" son iguales");
667
    }
668
}