Statistics
| Revision:

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

History | View | Annotate | Download (31.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.csv.xml;
7

    
8
import java.io.BufferedReader;
9
import java.io.Closeable;
10
import java.io.File;
11
import java.io.IOException;
12
import java.io.Reader;
13
import java.nio.ByteBuffer;
14
import java.nio.CharBuffer;
15
import java.nio.charset.Charset;
16
import java.nio.charset.StandardCharsets;
17
import java.util.AbstractList;
18
import java.util.ArrayList;
19
import java.util.HashMap;
20
import java.util.List;
21
import java.util.Map;
22
import java.util.Objects;
23
import javax.xml.parsers.SAXParser;
24
import javax.xml.parsers.SAXParserFactory;
25
import org.apache.commons.collections4.CollectionUtils;
26
import org.apache.commons.io.FilenameUtils;
27
import org.apache.commons.io.IOUtils;
28
import org.apache.commons.io.input.CloseShieldReader;
29
import org.apache.commons.lang3.StringUtils;
30
import org.gvsig.fmap.dal.store.csv.RecordsFile;
31
import org.gvsig.fmap.dal.store.csv.RecordsFile.Record;
32
import org.gvsig.fmap.dal.store.csv.RecordsFile.RecordType;
33
import static org.gvsig.fmap.dal.store.csv.RecordsFile.RecordTypeBuilder.recordTypeBuilder;
34
import org.gvsig.fmap.dal.store.csv.RecordsFileImpl;
35
import org.gvsig.fmap.dal.store.csv.virtualrows.RandomAccessFileReader;
36
import org.gvsig.fmap.geom.Geometry;
37
import org.gvsig.fmap.geom.GeometryLocator;
38
import org.gvsig.tools.library.impl.DefaultLibrariesInitializer;
39
import org.gvsig.tools.util.GetItemWithSize64;
40
import org.xml.sax.Attributes;
41
import org.xml.sax.InputSource;
42
import org.xml.sax.Locator;
43
import org.xml.sax.SAXException;
44
import org.xml.sax.helpers.DefaultHandler;
45

    
46
/**
47
 *
48
 * @author jjdelcerro
49
 */
50
@SuppressWarnings("UseSpecificCatch")
51
public class XMLFileAsList
52
        extends AbstractList<List<String>>
53
        implements Closeable, GetItemWithSize64<List<String>> {
54
    
55
    public static final int COMBINE_NONE = 0;
56
    public static final int COMBINE_FIRST_NOT_NULL = 1;
57

    
58
    private static final int IDXFIELD_BEGINLINE = 0;
59
    private static final int IDXFIELD_BEGINCOLUMN = 1;
60
    private static final int IDXFIELD_BEGINRECORDPOS = 2;
61
    private static final int IDXFIELD_ENDLINE = 3;
62
    private static final int IDXFIELD_ENDCOLUMN = 4;
63
    
64
    private static final int IDXFIELD_BEGINGEOMLINE = 5;
65
    private static final int IDXFIELD_BEGINGEOMCOLUMN = 6;
66
    private static final int IDXFIELD_BEGINGEOMPOS = 7;
67
    private static final int IDXFIELD_ENDGEOMLINE = 8;
68
    private static final int IDXFIELD_ENDGEOMCOLUMN = 9;
69
    private static final int IDXFIELD_ENDGEOMPOS = 10;
70

    
71
            
72
    private final RandomAccessFileReader reader;
73
    private final String recordPath;
74
    private RecordsFile index;
75
    private List<String> fieldPaths;
76
    private List<String> geomPaths;
77
    private int combineMode;
78

    
79
    
80
    //                                                         ruta   recordnum                       ruta   recordnum
81
 // public XMLFileAsList(File text, Charset charset, List<Pair<String,Integer>> recordPath, List<Pair<String,Integer>> fieldPaths) throws IOException {
82
    public XMLFileAsList(File text, Charset charset, String recordPath, List<String> geomPath, List<String> fieldPaths) throws IOException {
83
        this.reader = new RandomAccessFileReader(text, charset);
84
        this.index = null;
85
        this.recordPath = recordPath;
86
        this.geomPaths = geomPath;
87
    }
88

    
89
    public XMLFileAsList(File text, File index, Charset charset, String recordPath, List<String> geomPath, List<String> fieldPaths) throws IOException {
90
        this.reader = new RandomAccessFileReader(text, charset);
91
        this.recordPath = recordPath;
92
        this.geomPaths = geomPath;
93
        this.fieldPaths = fieldPaths;
94
        if (index.exists()) {
95
            // TODO: Force to create index if text newer than index
96
            this.index = new RecordsFileImpl(index);
97
        } else {
98
            this.createIndex(index);
99
        }
100
    }
101

    
102
    public XMLFileAsList(RandomAccessFileReader reader, RecordsFile index, String recordPath, List<String> geomPath, List<String> fieldPaths) throws IOException {
103
        this.reader = reader;
104
        this.index = index;
105
        this.recordPath = recordPath;
106
        this.geomPaths = geomPath;
107
    }
108

    
109
    @Override
110
    public void close() {
111
        IOUtils.closeQuietly(this.reader);
112
        IOUtils.closeQuietly(this.index);
113
    }
114

    
115
    private List<String> getRecord(long position, List<String> fieldPaths) {
116
        class StopParserSAXException extends SAXException {
117
        }
118

    
119
        class ParseRecordsHandler extends DefaultHandler {
120

    
121
            Locator locator;
122
            List<String> path = new ArrayList<>();
123
            Map<String, String> record = new HashMap<>();
124
            StringBuilder value = new StringBuilder();
125
            List<String> values = new ArrayList<>();
126
            private int endLineNumber;
127
            private int endColumnNumber;
128

    
129
            @Override
130
            public void setDocumentLocator(Locator locator) {
131
                this.locator = locator;
132
            }
133

    
134
            @Override
135
            public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
136
                localName = removeNamespace(qName);
137
                path.add(localName);
138
                String path_s = StringUtils.join(path, "/");
139
                if (StringUtils.equalsIgnoreCase(path_s, recordPath)) {
140
                    return;
141
                }
142
                this.value.setLength(0);
143
                for (int i = 0; i < attributes.getLength(); i++) {
144
                    String attrPath = path_s+"/"+removeNamespace(attributes.getQName(i));
145
                    for (String fieldPath : fieldPaths) {
146
                        if (StringUtils.equalsIgnoreCase(attrPath, fieldPath)) {
147
                            record.put(fieldPath, attributes.getValue(i));
148
                            // No break to handle repeated columns
149
                        }
150
                    }
151
                }
152
            }
153

    
154
            @Override
155
            public void characters(char[] ch, int start, int length) throws SAXException {
156
                value.append(new String(ch, start, length));
157
            }
158

    
159
            private String removeNamespace(String s){
160
                if(s.indexOf(':') < 0){
161
                    return s;
162
                }
163
                String[] ss = s.split(":");
164
                return ss[1];
165
            }
166
            
167
            @Override
168
            public void endElement(String uri, String localName, String qName) throws SAXException {
169
                localName = removeNamespace(qName);
170
                String path_s = StringUtils.join(path, "/");
171

    
172
                for (String fieldPath : fieldPaths) {
173
                    if (StringUtils.equalsIgnoreCase(path_s, fieldPath)) {
174
                        record.put(fieldPath, this.value.toString());
175
                        // No break to handle repeated columns
176
                    }
177
                }
178

    
179
                if (this.locator.getLineNumber() >= this.endLineNumber
180
                        && this.locator.getColumnNumber() >= this.endColumnNumber) {
181
                    for (String fieldPath : fieldPaths) {
182
                        values.add(record.get(fieldPath));
183
                    }
184
                    throw new StopParserSAXException();
185
                }
186

    
187
                path.remove(path.size() - 1);
188
            }
189
        }
190

    
191
        System.out.println("RECORD "+position);
192
        ParseRecordsHandler handler = null;
193
        Record record = this.index.get64(position);
194
        try {
195
            long recordPosition = record.getLong(IDXFIELD_BEGINRECORDPOS);
196
            this.reader.seek(recordPosition);
197
            BufferedReader breader = new BufferedReader(this.reader, 1024 * 8);
198

    
199
            InputSource is = new InputSource(CloseShieldReader.wrap(breader));
200
            SAXParserFactory spf = SAXParserFactory.newInstance();
201
            spf.setNamespaceAware(false);
202
            SAXParser saxParser = spf.newSAXParser();
203
            handler = new ParseRecordsHandler();
204
            handler.endLineNumber=(int) (record.getLong(IDXFIELD_ENDLINE)-record.getLong(IDXFIELD_BEGINLINE)+1);
205
//            if(record.getLong(IDXFIELD_ENDLINE)==record.getLong(IDXFIELD_BEGINLINE)){
206
//                handler.endColumnNumber=(int) (record.getLong(IDXFIELD_ENDCOLUMN)-record.getLong(IDXFIELD_BEGINCOLUMN));
207
//            } else {
208
                handler.endColumnNumber=(int) record.getLong(IDXFIELD_ENDCOLUMN);
209
//            }
210

    
211
            saxParser.parse(is, handler);
212
        } catch (StopParserSAXException ex) {
213
            //Do nothing
214
        } catch (Exception ex) {
215
            throw new RuntimeException("Can't parse record " + position, ex);
216
        }
217
        if (handler == null) {
218
            return null;
219
        }
220
        try {
221
            Geometry geom = null;
222
            if(CollectionUtils.isNotEmpty(this.geomPaths)) {
223
                for (int i = 0; i < this.geomPaths.size(); i++) {
224
                    long geomPosition = record.getLong(IDXFIELD_BEGINGEOMPOS+i*6);
225
                    long endGeomPosition = record.getLong(IDXFIELD_ENDGEOMPOS+i*6);
226
                    if(geomPosition == 0 || endGeomPosition == 0){
227
                        if(this.combineMode != COMBINE_FIRST_NOT_NULL){
228
                            handler.values.add(null);
229
                        }
230
                        continue;
231
                    }
232
                    this.reader.seek(geomPosition);
233
                    if(position == 0){
234
                        char[] cbuff = new char[(int)(endGeomPosition-geomPosition)];
235
                        this.reader.read(cbuff);
236
                        System.out.println("["+new String(cbuff)+"]");
237
                        this.reader.seek(geomPosition);
238
                    }
239
                    Reader limitedReader = new LimitedReader(reader, (int)(endGeomPosition-geomPosition));
240
                    BufferedReader breader = new BufferedReader(limitedReader, 1024 * 8);
241
                    geom = GeometryLocator.getGeometryManager().createFrom(breader, null);
242
                    if(this.combineMode == COMBINE_FIRST_NOT_NULL){
243
                        if(geom != null){
244
                            handler.values.add(geom.convertToHexEWKB());
245
                            break;
246
                        }
247
                    } else {
248
                        handler.values.add(geom.convertToHexEWKB());
249
                    }
250
                }
251
                if(this.combineMode == COMBINE_FIRST_NOT_NULL && geom == null){
252
                    handler.values.add(null);
253
                }
254
            }
255
            
256
        } catch (Exception ex) {
257
            throw new RuntimeException("Can't parse record " + position, ex);
258
        }
259
        return handler.values;
260
    }
261

    
262
    @Override
263
    public List<String> get(int index) {
264
        return this.getRecord(index, fieldPaths);
265
    }
266

    
267
    @Override
268
    public List<String> get64(long position) {
269
        return this.getRecord(position, fieldPaths);
270
    }
271

    
272
    @Override
273
    public int size() {
274
        return this.index.size();
275
    }
276

    
277
    @Override
278
    public long size64() {
279
        return this.index.size64();
280
    }
281

    
282
    public int getCombineMode() {
283
        return combineMode;
284
    }
285
    
286
    public void setCombineMode(int combineMode) {
287
        this.combineMode = combineMode;
288
    }
289

    
290
    final public void createIndex(File indexFile) throws IOException {
291
        try {
292
            // 1. Creamos el indice vacio
293
            RecordsFile.RecordTypeBuilder builder = recordTypeBuilder()
294
                    .addLong()
295
                    .addLong()
296
                    .addLong()
297
                    .addLong()
298
                    .addLong();
299

    
300
            if (CollectionUtils.isNotEmpty(geomPaths)) {
301
                for (String geomPath : geomPaths) {
302
                    builder.addLong()
303
                            .addLong()
304
                            .addLong()
305
                            .addLong()
306
                            .addLong()
307
                            .addLong();
308
                }
309
            }
310
            RecordType recordType = builder.build();
311
            Record record = recordType.createRecord();
312
            final RecordsFile theIndex = new RecordsFileImpl();
313
            theIndex.create(indexFile, recordType);
314

    
315
            // 2. Rellenamos los campos numero de linea y columna de cada registro 
316
            //    en el indice.
317
            // Para ello nos recorremos el XML y vamos escribiendo en el indice.
318
            this.reader.rewind();
319
            InputSource is = new InputSource(CloseShieldReader.wrap(reader));
320
            SAXParserFactory spf = SAXParserFactory.newInstance();
321
            spf.setNamespaceAware(true);
322
            SAXParser saxParser = spf.newSAXParser();
323

    
324
            List<String> path = new ArrayList<>();
325
            // TODO: Aqui habria que quedarse con la primera aparicion de
326
            // los campos solicitados que no pertenezcan al registro principal.
327
            // Probablemente habria que guardar esos valores en disco junto al
328
            // fichero de indice.
329
            saxParser.parse(is, new DefaultHandler() {
330
                Locator locator;
331
                private int beginLineNumber;
332
                private int beginColumnNumber;
333
                private int lastTagLineNumber;
334
                private int lastTagColumnNumber;
335

    
336
                @Override
337
                public void setDocumentLocator(Locator locator) {
338
                    this.locator = locator;
339
                }
340

    
341
                @Override
342
                public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
343
                    path.add(localName);
344
                    String path_s = StringUtils.join(path, "/");
345
                    
346
                    
347
                    if (StringUtils.equalsIgnoreCase(path_s, recordPath)) {
348
                        record.setLong(IDXFIELD_BEGINLINE, locator.getLineNumber());
349
                        record.setLong(IDXFIELD_BEGINCOLUMN, locator.getColumnNumber());
350
                        record.setLong(IDXFIELD_ENDLINE, 0);
351
                        record.setLong(IDXFIELD_ENDCOLUMN, 0);
352
                        if(CollectionUtils.isNotEmpty(geomPaths)) {
353
                            for (int i = 0; i < geomPaths.size(); i++) {
354
                                record.setLong(IDXFIELD_BEGINGEOMLINE+6*i, 0);
355
                                record.setLong(IDXFIELD_BEGINGEOMCOLUMN+6*i, 0);
356
                                record.setLong(IDXFIELD_BEGINGEOMPOS+6*i, 0);
357
                                record.setLong(IDXFIELD_ENDGEOMLINE+6*i, 0);
358
                                record.setLong(IDXFIELD_ENDGEOMCOLUMN+6*i, 0);
359
                                record.setLong(IDXFIELD_ENDGEOMPOS+6*i, 0);
360
                            }
361
                        }
362
                        this.beginLineNumber = locator.getLineNumber();
363
                        this.beginColumnNumber = locator.getColumnNumber();
364
                    }
365
                    if(CollectionUtils.isNotEmpty(geomPaths)) {
366
                        for (int i = 0; i < geomPaths.size(); i++) {
367
                            String geomPath = geomPaths.get(i);
368
                            if (StringUtils.equalsIgnoreCase(path_s, recordPath+"/"+geomPath)) {
369
                                record.setLong(IDXFIELD_BEGINGEOMLINE+6*i, locator.getLineNumber());
370
                                record.setLong(IDXFIELD_BEGINGEOMCOLUMN+6*i, locator.getColumnNumber());
371
                                record.setLong(IDXFIELD_BEGINGEOMPOS+6*i, 0);
372
                                break;
373
                            }
374
                        }
375
                    }
376

    
377
                }
378

    
379
                @Override
380
                public void endElement(String uri, String localName, String qName) throws SAXException {
381
                    String path_s = StringUtils.join(path, "/");
382
                    
383
                    if (StringUtils.equalsIgnoreCase(path_s, recordPath)) {
384
                        int line = lastTagLineNumber;//-this.beginLineNumber;
385
                        int column = this.lastTagColumnNumber;
386
                        if(line==0){
387
                            column = column - this.beginColumnNumber;
388
                        }
389
                        record.setLong(IDXFIELD_ENDLINE, line);
390
                        record.setLong(IDXFIELD_ENDCOLUMN, column);
391
                        theIndex.add(record);
392
                    }
393
                    if(CollectionUtils.isNotEmpty(geomPaths)) {
394
                        for (int i = 0; i < geomPaths.size(); i++) {
395
                            String geomPath = geomPaths.get(i);
396
                            if (StringUtils.equalsIgnoreCase(path_s, recordPath+"/"+geomPath)) {
397
                                record.setLong(IDXFIELD_ENDGEOMLINE+6*i, this.lastTagLineNumber);
398
                                record.setLong(IDXFIELD_ENDGEOMCOLUMN+6*i, this.lastTagColumnNumber);
399
                                break;
400
                            }
401
                        }
402
                    }
403
                    this.lastTagLineNumber = locator.getLineNumber();
404
                    this.lastTagColumnNumber = locator.getColumnNumber();
405
                    path.remove(path.size() - 1);
406
                }
407
            });
408

    
409
            // 3. Nos recorremos el indice y calculamos la posicion de la linea
410
            //    para cada registro.
411
            this.reader.rewind();
412
            PositionCalculator positionCalculator = new PositionCalculator(reader);
413

    
414
            for (int j = 0; j < theIndex.size(); j++) {
415
                Record r = theIndex.get(j);
416
//                if(i==0){
417
                    System.out.println("RECO BEGIN: "+r.getLong(IDXFIELD_BEGINLINE) + " " + r.getLong(IDXFIELD_BEGINCOLUMN));
418
                    if(CollectionUtils.isNotEmpty(geomPaths)) {
419
                        for (int i = 0; i < geomPaths.size(); i++) {
420
                            System.out.println("GEOM"+i+"BEGIN: "+r.getLong(IDXFIELD_BEGINGEOMLINE+i*6) + " " + r.getLong(IDXFIELD_BEGINGEOMCOLUMN+i*6));
421
                            System.out.println("GEOM"+i+"END  : "+r.getLong(IDXFIELD_ENDGEOMLINE+i*6) + " " +  r.getLong(IDXFIELD_ENDGEOMCOLUMN+i*6));
422
                        }
423
                    }
424
                    System.out.println("RECO END  : "+r.getLong(IDXFIELD_ENDLINE) + " " +  r.getLong(IDXFIELD_ENDCOLUMN));
425
//                }
426
                positionCalculator.next(r.getLong(IDXFIELD_BEGINLINE), r.getLong(IDXFIELD_BEGINCOLUMN));
427
                r.setLong(IDXFIELD_BEGINRECORDPOS, positionCalculator.getColumnPosition());
428
                System.out.println("RPOS      : " + r.getLong(IDXFIELD_BEGINRECORDPOS));
429
                if(CollectionUtils.isNotEmpty(geomPaths)) {
430
                    for (int i = 0; i < geomPaths.size(); i++) {
431
                        long beginGeomLine = r.getLong(IDXFIELD_BEGINGEOMLINE + i * 6);
432
                        long endGeomLine = r.getLong(IDXFIELD_ENDGEOMLINE + i * 6);
433
                        if (beginGeomLine == 0 || endGeomLine == 0) {
434
                            continue;
435
                        }
436
                        positionCalculator.next(beginGeomLine, r.getLong(IDXFIELD_BEGINGEOMCOLUMN + i * 6));
437
                        r.setLong(IDXFIELD_BEGINGEOMPOS + i * 6, positionCalculator.getColumnPosition());
438
                        positionCalculator.next(endGeomLine, r.getLong(IDXFIELD_ENDGEOMCOLUMN + i * 6));
439
                        r.setLong(IDXFIELD_ENDGEOMPOS + i * 6, positionCalculator.getColumnPosition());
440
                        System.out.println("GPOS" + i + "     : " + r.getLong(IDXFIELD_BEGINGEOMPOS + i * 6) + " " + r.getLong(IDXFIELD_ENDGEOMPOS + i * 6));
441
                    }
442
                }
443
                theIndex.set(j, r);
444
//                if(i==0){
445
//                }
446
            }
447
            this.index = new RecordsFileImpl(indexFile);
448
        } catch (Exception ex) {
449
            throw new IOException("Can't create index " + Objects.toString(indexFile), ex);
450
        }
451
    }
452
    
453
    private static class LimitedReader extends Reader {
454

    
455
        private final Reader delegated;
456
        private final int limit;
457
        private int count;
458
        
459
        public LimitedReader(Reader reader, int limit) {
460
            this.delegated = reader;
461
            this.limit = limit;
462
        }
463

    
464
        @Override
465
        public int read(char[] cbuf, int off, int len) throws IOException {
466
            if(count >= limit){
467
                return -1;
468
            }
469
            if(count+len > limit){
470
                len = limit - count;
471
            }
472
            if(len==0){
473
                return -1;
474
            }
475
            int n = this.delegated.read(cbuf, off, len);
476
            if(count+n <= limit){
477
                count += n;
478
                return n;
479
            }
480
            return limit - count;
481
            
482
        }
483

    
484
        @Override
485
        public void close() throws IOException {
486
//            this.delegated.close();
487
        }
488

    
489
        @Override
490
        public int read(java.nio.CharBuffer target) throws IOException {
491
            return this.delegated.read(target);
492
        }
493

    
494
        @Override
495
        public int read() throws IOException {
496
            return this.delegated.read();
497
        }
498

    
499
        @Override
500
        public int read(char cbuf[]) throws IOException {
501
            return this.delegated.read(cbuf);
502
        }
503

    
504
        @Override
505
        public long skip(long n) throws IOException {
506
            return this.delegated.skip(n);
507
        }
508

    
509
        @Override
510
        public boolean ready() throws IOException {
511
            return this.delegated.ready();
512
        }
513

    
514
        @Override
515
        public boolean markSupported() {
516
            return this.delegated.markSupported();
517
        }
518

    
519
        @Override
520
        public void mark(int readAheadLimit) throws IOException {
521
            this.delegated.mark(readAheadLimit);
522
        }
523

    
524
        @Override
525
        public void reset() throws IOException {
526
            this.delegated.reset();
527
        }
528
    }
529

    
530
    private static class CharacterSize {
531

    
532
        private final Charset charset;
533
        private final CharBuffer charBuffer;
534

    
535
        public CharacterSize(Charset charset) {
536
            this.charset = charset;
537
            this.charBuffer = CharBuffer.allocate(1);
538
        }
539

    
540
        public int size(char ch) {
541
            this.charBuffer.put(0, ch);
542
            this.charBuffer.position(0);
543
            ByteBuffer buffer = this.charset.encode(this.charBuffer);
544
            return buffer.limit();
545
        }
546

    
547
        public int size(char[] cbuf, int off, int len) {
548
            CharBuffer cb = CharBuffer.wrap(cbuf, off, len);
549
            ByteBuffer byteBuffer = this.charset.encode(cb);
550
            return byteBuffer.limit();
551
        }
552

    
553
        public int size(char[] cbuf) {
554
            CharBuffer cb = CharBuffer.wrap(cbuf, 0, cbuf.length);
555
            ByteBuffer byteBuffer = this.charset.encode(cb);
556
            return byteBuffer.limit();
557
        }
558

    
559
        public int size(String s) {
560
            CharBuffer cb = CharBuffer.wrap(s);
561
            ByteBuffer byteBuffer = this.charset.encode(cb);
562
            return byteBuffer.limit();
563
        }
564
    }
565

    
566
    private static class PositionCalculator {
567

    
568
        private final RandomAccessFileReader reader;
569
        private final BufferedReader breader;
570
        private long currentPosition;
571
        private long currentColumn;
572
        private long currentLine;
573
        private long currentColumnPosition;
574
        private long currentLinePosition;
575

    
576
        private final char[] ch;
577
        private final CharacterSize characterSize;
578

    
579
        public PositionCalculator(RandomAccessFileReader reader) {
580
            this.reader = reader;
581
            this.breader = new BufferedReader(this.reader, 1024 * 8);
582
            this.currentPosition = this.reader.getCurrentPosition();
583
            this.currentLine = 1;
584
            this.currentColumn = 1;
585
            this.ch = new char[1];
586
            this.characterSize = new CharacterSize(this.reader.getCharset());
587
        }
588

    
589
        public boolean next(long line, long column) throws IOException {
590
            System.out.println();
591
            System.out.println("----"+line+" "+column);
592
            if(this.currentLine>line){
593
                throw new IOException("Illegal column number " + column + " ("+this.currentColumn+") for line " + line+ " ("+this.currentLine+")");
594
            }
595
            if(this.currentLine==line && this.currentColumn > column){
596
                throw new IOException("Illegal column number " + column + " ("+this.currentColumn+") for line " + line);
597
            }
598
            System.out.print(this.currentLine+":");
599
            while (this.currentLine < line) {
600
                if (breader.read(this.ch, 0, 1) < 1) {
601
                    return false;
602
                }
603
                char c = ch[0];
604
                System.out.print(String.valueOf(c));
605
                this.currentPosition += characterSize.size(c);
606
                if (c == '\n') {
607
                    this.currentLine++;
608
                    this.currentColumn = 1;
609
                    System.out.print(this.currentLine+":");
610
                }
611
            }
612
            this.currentLinePosition = this.currentPosition;
613
            while (true) { //this.currentColumn < column) {
614
                if (breader.read(this.ch, 0, 1) < 1) {
615
                    return false;
616
                }
617
                char c = ch[0];
618
                System.out.print(String.valueOf(c));
619
                this.currentColumn++;
620
                this.currentPosition += characterSize.size(c);
621
                if(this.currentColumn >= column){
622
                    break;
623
                }
624
                if (c == '\n') {
625
//                    if (this.currentColumn < column) {
626
                        // Uff, esto seria un error, ya que la linea corriente no
627
                        // tiene tantas columnas.
628
                        throw new IOException("Illegal column number " + column + " ("+this.currentColumn+") for line " + line+ " ("+this.currentLine+")");
629
//                    }
630
//                    this.currentLine++;
631
                }
632
            }
633
            this.currentColumnPosition = this.currentPosition;
634
            System.out.println();
635
            return true;
636
        }
637

    
638
        public long getLinePosition() {
639
            return this.currentLinePosition;
640
        }
641

    
642
        public long getColumnPosition() {
643
            return this.currentColumnPosition;
644
        }
645

    
646
    }
647

    
648
    public static void main(String[] args) throws Exception {
649
        new DefaultLibrariesInitializer().fullInitialize();
650

    
651
//        final String XMLFILE1 = "/home/jjdelcerro/datos/geodata/vector/gml/navarra.gml";
652
//        final String XMLFILE2 = "/home/jjdelcerro/datos/geodata/vector/gml/Municipis/Municipis.gml";
653
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/1075305YJ2717N.gml";
654
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/Recinto.gml";
655
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/FG-GML-543863-AdmBdry-20190101-0001.gml";
656
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/Municipis.gml";
657
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/navarra.gml";
658
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/Falls.gml";
659
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/StandingWater.gml";
660
        
661
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/EmbankmentL.gml";
662
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/AerodromeType.gml"; //No tiene geometr?as
663
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/SurfaceComposition.gml";
664
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/ShorelineConstructionL.gml";
665
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/AerodromeArea.gml";
666
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/DamOrWeirL.gml";
667
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RunwayArea.gml";
668
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RailwayStationArea.gml";
669
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/DamOrWeirS.gml";
670
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/Road.gml"; //No tiene geometr?as
671
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/CablewayLink.gml";
672
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RailwayYardArea.gml";
673
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/WatercourseLinkSequence.gml"; //No tiene geometr?as
674
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/EmbankmentS.gml";
675
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/FordP.gml";
676
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RoadServiceType.gml"; //No tiene geometr?as
677
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/Wetland.gml";
678
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RailwayElectrification.gml"; //No tiene geometr?as
679
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RailwayType.gml"; //No tiene geometr?as
680
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/NumberOfTracks.gml"; //No tiene geometr?as
681
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RoadServiceArea.gml";
682
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/NominalTrackGauge.gml"; //No tiene geometr?as
683
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RailwayArea.gml";
684
        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/CrossingS.gml";
685
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/CrossingP.gml";
686
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/StandingWater.gml";
687
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RailwayLink.gml";
688
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/BuildingP.gml";
689
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/INSPIRE_GN.gml";
690
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/INSPIRE_AU.gml";
691
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/WatercourseLink.gml";
692
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/Watercourse.gml";
693
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/FormOfWay.gml";
694
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RoadArea.gml";
695
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RoadSurfaceCategory.gml";
696
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/FunctionalRoadClass.gml";
697
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/ConditionOfFacility.gml";
698
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RoadWidth.gml";
699
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/VerticalPosition.gml";
700
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RoadLink.gml";
701

    
702

    
703
        String gmlfile = XMLFILE1;
704
        File idxFile = new File(FilenameUtils.removeExtension(gmlfile)+".gmlidx");
705
        if(idxFile.exists()){
706
            idxFile.delete();
707
        }
708
        File gfsFile = new File(FilenameUtils.removeExtension(gmlfile)+".gfs");
709
        if(gfsFile.exists()){
710
            gfsFile.delete();
711
        }
712
        GfsFile gfs = new GfsFile();
713
        gfs.fetch(new File(gmlfile));
714
        gfs.save(gfsFile);
715
//        return;
716
        XMLFileAsList gml = new XMLFileAsList(
717
                new File(gmlfile), 
718
                new File(FilenameUtils.removeExtension(gmlfile)+".gmlidx"), 
719
//                StandardCharsets.ISO_8859_1, 
720
                StandardCharsets.UTF_8, 
721
                gfs.getBaseElementPath(),
722
                gfs.getGeometryElementPaths(),
723
                gfs.getPropertiesPaths()
724
        );
725
        System.out.println("File: "+gmlfile);
726
        for (int i = 0; i < gml.size(); i++) {
727
            List<String> item = gml.get(i);
728
            System.out.println("RECORD "+i+":"+item);
729
        }
730
        System.out.println(StringUtils.join(gfs.getPropertiesPaths(), "\n"));
731
    }
732
}