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

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.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.xmlinfo.XMLAttributeInfoImpl;
24
import org.gvsig.fmap.dal.store.gml.virtualrows.xmlinfo.XMLInfoImpl;
25
import org.gvsig.fmap.dal.store.gml.virtualrows.GfsFile.PropertyDefn;
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

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

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

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

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

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

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

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

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

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

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

    
260

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

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

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

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

    
304
            }
305

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

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

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

    
393
            }
394

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

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

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

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

    
465
                    path.add(localName);
466

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

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

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

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

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

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

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

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