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 @ 47655

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
        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
            for (String geometryElementPath : getGeometryElementPaths()) {
308
                builder.append("    <GeometryElementPath>"+geometryElementPath+"</GeometryElementPath>\n");
309
            }
310
            for (String geometryElementSrs : getGeometryElementSrss()) {
311
                builder.append("    <GeometryElementSrs>"+geometryElementSrs+"</GeometryElementSrs>\n");
312
            }
313
            for (PropertyDefn property : properties.values()) {
314
                int type = property.getType();
315
                String propertyType = datatypesManager.getTypeName(type);
316

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

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

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

    
342
            }
343

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

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

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

    
432
            }
433

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

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

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

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

    
504
                    path.add(localName);
505

    
506
                    chars.setLength(0);
507
                    
508
                }
509

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

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

    
558
            }
559
            );
560
            status.terminate();
561

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

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

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

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