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 / XMLFileAsList.java @ 47665

History | View | Annotate | Download (31.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.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 static org.gvsig.fmap.dal.store.simplereader.SimpleReaderUtils.isFileNewer;
31
import org.gvsig.fmap.dal.store.simplereader.virtualrows.LimitedReader;
32
import org.gvsig.fmap.dal.store.simplereader.virtualrows.RandomAccessFileReader;
33
import org.gvsig.fmap.dal.store.simplereader.virtualrows.RecordsFile;
34
import org.gvsig.fmap.dal.store.simplereader.virtualrows.RecordsFile.Record;
35
import org.gvsig.fmap.dal.store.simplereader.virtualrows.RecordsFile.RecordType;
36
import static org.gvsig.fmap.dal.store.simplereader.virtualrows.RecordsFile.RecordTypeBuilder.recordTypeBuilder;
37
import org.gvsig.fmap.dal.store.simplereader.virtualrows.RecordsFileImpl;
38
import org.gvsig.fmap.geom.Geometry;
39
import org.gvsig.fmap.geom.GeometryLocator;
40
import org.gvsig.tools.ToolsLocator;
41
import org.gvsig.tools.i18n.I18nManager;
42
import org.gvsig.tools.library.impl.DefaultLibrariesInitializer;
43
import org.gvsig.tools.task.SimpleTaskStatus;
44
import org.gvsig.tools.task.UserCancelTaskException;
45
import org.gvsig.tools.util.GetItemWithSize64;
46
import org.xml.sax.Attributes;
47
import org.xml.sax.InputSource;
48
import org.xml.sax.Locator;
49
import org.xml.sax.SAXException;
50
import org.xml.sax.helpers.DefaultHandler;
51

    
52
/**
53
 *
54
 * @author jjdelcerro
55
 */
56
@SuppressWarnings("UseSpecificCatch")
57
public class XMLFileAsList
58
        extends AbstractList<List<String>>
59
        implements Closeable, GetItemWithSize64<List<String>> {
60
    
61
    public static final int COMBINE_NONE = 0;
62
    public static final int COMBINE_FIRST_NOT_NULL = 1;
63

    
64
    private static final int IDXFIELD_BEGINLINE = 0; //INTEGER
65
    private static final int IDXFIELD_BEGINCOLUMN = 1; //INTEGER
66
    private static final int IDXFIELD_BEGINRECORDPOS = 2; //LONG
67
    private static final int IDXFIELD_ENDLINE = 3; //INTEGER
68
    private static final int IDXFIELD_ENDCOLUMN = 4; //INTEGER
69
    
70
    private static final int IDXFIELD_BEGINGEOMLINE = 5; //INTEGER
71
    private static final int IDXFIELD_BEGINGEOMCOLUMN = 6; //INTEGER
72
    private static final int IDXFIELD_BEGINGEOMPOS = 7; //LONG
73
    private static final int IDXFIELD_ENDGEOMLINE = 8; //INTEGER
74
    private static final int IDXFIELD_ENDGEOMCOLUMN = 9; //INTEGER
75
    private static final int IDXFIELD_ENDGEOMPOS = 10; //LONG
76

    
77
            
78
    private final RandomAccessFileReader reader;
79
    private final String recordPath;
80
    private RecordsFile index;
81
    private List<String> fieldPaths;
82
    private final List<String> geomPaths;
83
    private int combineMode;
84
    private long lastModified;
85

    
86
    
87
    public XMLFileAsList(File text, Charset charset, String recordPath, List<String> geomPath, List<String> fieldPaths) throws IOException {
88
        this.reader = new RandomAccessFileReader(text, charset);
89
        this.index = null;
90
        this.recordPath = recordPath;
91
        this.geomPaths = geomPath;
92
        this.fieldPaths = fieldPaths;
93
        this.lastModified = text.lastModified();
94
    }
95

    
96
    public XMLFileAsList(RandomAccessFileReader reader, RecordsFile index, String recordPath, List<String> geomPath, List<String> fieldPaths) throws IOException {
97
        this.reader = reader;
98
        this.index = index;
99
        this.recordPath = recordPath;
100
        this.geomPaths = geomPath;
101
        this.fieldPaths = fieldPaths;
102
        this.lastModified = -1;
103
    }
104

    
105
    @Override
106
    public void close() {
107
        IOUtils.closeQuietly(this.reader);
108
        IOUtils.closeQuietly(this.index);
109
    }
110

    
111
    private List<String> getRecord(long position, List<String> fieldPaths) {
112
        class StopParserSAXException extends SAXException {
113
        }
114

    
115
        class ParseRecordsHandler extends DefaultHandler {
116

    
117
            Locator locator;
118
            List<String> path = new ArrayList<>();
119
            Map<String, String> record = new HashMap<>();
120
            StringBuilder value = new StringBuilder();
121
            List<String> values = new ArrayList<>();
122
            private int endLineNumber;
123
            private int endColumnNumber;
124

    
125
            @Override
126
            public void setDocumentLocator(Locator locator) {
127
                this.locator = locator;
128
            }
129

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

    
150
            @Override
151
            public void characters(char[] ch, int start, int length) throws SAXException {
152
                value.append(new String(ch, start, length));
153
            }
154

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

    
168
                for (String fieldPath : fieldPaths) {
169
                    if (StringUtils.equalsIgnoreCase(path_s, fieldPath)) {
170
                        record.put(fieldPath, this.value.toString());
171
                        // No break to handle repeated columns
172
                    }
173
                }
174

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

    
183
                path.remove(path.size() - 1);
184
            }
185
        }
186

    
187
//        System.out.println("RECORD "+position);
188
        ParseRecordsHandler handler = null;
189
        Record record = this.index.get64(position);
190
        try {
191
            long recordPosition = record.getLong(IDXFIELD_BEGINRECORDPOS);
192
            this.reader.seek(recordPosition);
193
            // TODO: guardarse el tama?o del registro en el indice y en funcion de eso usar un buffersize mas peque?o aqui si procede
194
            int bufferSize = 1024*8; 
195
            BufferedReader breader = new BufferedReader(this.reader, bufferSize);
196

    
197
            InputSource is = new InputSource(CloseShieldReader.wrap(breader));
198
            SAXParserFactory spf = SAXParserFactory.newInstance();
199
            spf.setNamespaceAware(false);
200
            SAXParser saxParser = spf.newSAXParser();
201
            handler = new ParseRecordsHandler();
202
            handler.endLineNumber=(int) (record.getInt(IDXFIELD_ENDLINE)-record.getInt(IDXFIELD_BEGINLINE)+1);
203
            handler.endColumnNumber=(int) record.getInt(IDXFIELD_ENDCOLUMN);
204

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

    
258
    @Override
259
    public List<String> get(int index) {
260
        return this.getRecord(index, fieldPaths);
261
    }
262

    
263
    @Override
264
    public List<String> get64(long position) {
265
        return this.getRecord(position, fieldPaths);
266
    }
267

    
268
    @Override
269
    public int size() {
270
        return this.index.size();
271
    }
272

    
273
    @Override
274
    public long size64() {
275
        return this.index.size64();
276
    }
277

    
278
    public int getCombineMode() {
279
        return combineMode;
280
    }
281
    
282
    public void setCombineMode(int combineMode) {
283
        this.combineMode = combineMode;
284
    }
285
    
286
    public boolean loadIndex(File fileIndex, SimpleTaskStatus status) throws IOException{
287
        if (!fileIndex.exists()) {
288
            return false;
289
        }
290
        if(this.lastModified > 0 && isFileNewer(fileIndex, this.lastModified)){
291
            this.index = new RecordsFileImpl(fileIndex);
292
            return true;
293
        }
294
        return false;
295
    }
296
    
297
    final public void createIndex(File indexFile, SimpleTaskStatus status) throws IOException {
298
        try {
299
            // 1. Creamos el indice vacio
300
            RecordsFile.RecordTypeBuilder builder = recordTypeBuilder()
301
                    .addInteger()
302
                    .addInteger()
303
                    .addLong()
304
                    .addInteger()
305
                    .addInteger();
306

    
307
            if (CollectionUtils.isNotEmpty(geomPaths)) {
308
                for (int i = 0; i < geomPaths.size(); i++) {
309
                    builder.addInteger()
310
                            .addInteger()
311
                            .addLong()
312
                            .addInteger()
313
                            .addInteger()
314
                            .addLong();
315
                }
316
            }
317
            RecordType recordType = builder.build();
318
            Record record = recordType.createRecord();
319
            final RecordsFile theIndex = new RecordsFileImpl();
320
            theIndex.create(indexFile, recordType);
321

    
322
            // 2. Rellenamos los campos numero de linea y columna de cada registro 
323
            //    en el indice.
324
            // Para ello nos recorremos el XML y vamos escribiendo en el indice.
325
            this.reader.rewind();
326
            InputSource is = new InputSource(CloseShieldReader.wrap(reader));
327
            SAXParserFactory spf = SAXParserFactory.newInstance();
328
            spf.setNamespaceAware(true);
329
            SAXParser saxParser = spf.newSAXParser();
330
            
331
            if (status != null) {
332
                I18nManager i18n = ToolsLocator.getI18nManager();
333
                status.push();
334
                status.message(i18n.getTranslation("_Creating_record_index"));
335
                status.setIndeterminate();
336
            }
337

    
338
            List<String> path = new ArrayList<>();
339
            // TODO: Aqui habria que quedarse con la primera aparicion de
340
            // los campos solicitados que no pertenezcan al registro principal.
341
            // Probablemente habria que guardar esos valores en disco junto al
342
            // fichero de indice.
343
            saxParser.parse(is, new DefaultHandler() {
344
                Locator locator;
345
                private int beginLineNumber;
346
                private int beginColumnNumber;
347
                private int lastTagLineNumber;
348
                private int lastTagColumnNumber;
349

    
350
                @Override
351
                public void setDocumentLocator(Locator locator) {
352
                    this.locator = locator;
353
                }
354

    
355
                @Override
356
                public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
357
                    path.add(localName);
358
                    String path_s = StringUtils.join(path, "/");
359

    
360
                    if (StringUtils.equalsIgnoreCase(path_s, recordPath)) {
361
                        record.setInt(IDXFIELD_BEGINLINE, locator.getLineNumber());
362
                        record.setInt(IDXFIELD_BEGINCOLUMN, locator.getColumnNumber());
363
                        record.setInt(IDXFIELD_ENDLINE, 0);
364
                        record.setInt(IDXFIELD_ENDCOLUMN, 0);
365
                        if (CollectionUtils.isNotEmpty(geomPaths)) {
366
                            for (int i = 0; i < geomPaths.size(); i++) {
367
                                record.setInt(IDXFIELD_BEGINGEOMLINE + 6 * i, 0);
368
                                record.setInt(IDXFIELD_BEGINGEOMCOLUMN + 6 * i, 0);
369
                                record.setLong(IDXFIELD_BEGINGEOMPOS + 6 * i, 0);
370
                                record.setInt(IDXFIELD_ENDGEOMLINE + 6 * i, 0);
371
                                record.setInt(IDXFIELD_ENDGEOMCOLUMN + 6 * i, 0);
372
                                record.setLong(IDXFIELD_ENDGEOMPOS + 6 * i, 0);
373
                            }
374
                        }
375
                        this.beginLineNumber = locator.getLineNumber();
376
                        this.beginColumnNumber = locator.getColumnNumber();
377
                    }
378
                    if (CollectionUtils.isNotEmpty(geomPaths)) {
379
                        for (int i = 0; i < geomPaths.size(); i++) {
380
                            String geomPath = geomPaths.get(i);
381
                            if (StringUtils.equalsIgnoreCase(path_s, recordPath + "/" + geomPath)) {
382
                                record.setInt(IDXFIELD_BEGINGEOMLINE + 6 * i, locator.getLineNumber());
383
                                record.setInt(IDXFIELD_BEGINGEOMCOLUMN + 6 * i, locator.getColumnNumber());
384
                                record.setLong(IDXFIELD_BEGINGEOMPOS + 6 * i, 0);
385
                                break;
386
                            }
387
                        }
388
                    }
389
                    if (status != null) {
390
                        if (status.isCancellationRequested()) {
391
                            throw new UserCancelTaskException();
392
                        }
393
                    }
394
                }
395

    
396
                @Override
397
                public void endElement(String uri, String localName, String qName) throws SAXException {
398
                    String path_s = StringUtils.join(path, "/");
399

    
400
                    if (StringUtils.equalsIgnoreCase(path_s, recordPath)) {
401
                        int line = lastTagLineNumber;//-this.beginLineNumber;
402
                        int column = this.lastTagColumnNumber;
403
                        if (line == 0) {
404
                            column = column - this.beginColumnNumber;
405
                        }
406
                        record.setInt(IDXFIELD_ENDLINE, line);
407
                        record.setInt(IDXFIELD_ENDCOLUMN, column);
408
                        theIndex.add(record);
409
                    }
410
                    if (CollectionUtils.isNotEmpty(geomPaths)) {
411
                        for (int i = 0; i < geomPaths.size(); i++) {
412
                            String geomPath = geomPaths.get(i);
413
                            if (StringUtils.equalsIgnoreCase(path_s, recordPath + "/" + geomPath)) {
414
                                record.setInt(IDXFIELD_ENDGEOMLINE + 6 * i, this.lastTagLineNumber);
415
                                record.setInt(IDXFIELD_ENDGEOMCOLUMN + 6 * i, this.lastTagColumnNumber);
416
                                break;
417
                            }
418
                        }
419
                    }
420
                    this.lastTagLineNumber = locator.getLineNumber();
421
                    this.lastTagColumnNumber = locator.getColumnNumber();
422
                    path.remove(path.size() - 1);
423

    
424
                    if (status != null) {
425
                        if (status.isCancellationRequested()) {
426
                            throw new UserCancelTaskException();
427
                        }
428
                    }
429

    
430
                }
431
            });
432
            if (status != null) {
433
                status.setRangeOfValues(0, theIndex.size64());
434
                status.setCurValue(0);
435
            }
436

    
437
            // 3. Nos recorremos el indice y calculamos la posicion de la linea
438
            //    para cada registro.
439
            this.reader.rewind();
440
            PositionCalculator positionCalculator = new PositionCalculator(reader);
441

    
442
            for (int j = 0; j < theIndex.size(); j++) {
443
                Record r = theIndex.get(j);
444
//                if(i==0){
445
//                    System.out.println("RECO BEGIN: "+r.getLong(IDXFIELD_BEGINLINE) + " " + r.getLong(IDXFIELD_BEGINCOLUMN));
446
//                    if(CollectionUtils.isNotEmpty(geomPaths)) {
447
//                        for (int i = 0; i < geomPaths.size(); i++) {
448
//                            System.out.println("GEOM"+i+"BEGIN: "+r.getLong(IDXFIELD_BEGINGEOMLINE+i*6) + " " + r.getLong(IDXFIELD_BEGINGEOMCOLUMN+i*6));
449
//                            System.out.println("GEOM"+i+"END  : "+r.getLong(IDXFIELD_ENDGEOMLINE+i*6) + " " +  r.getLong(IDXFIELD_ENDGEOMCOLUMN+i*6));
450
//                        }
451
//                    }
452
//                    System.out.println("RECO END  : "+r.getLong(IDXFIELD_ENDLINE) + " " +  r.getLong(IDXFIELD_ENDCOLUMN));
453
//                }
454
                positionCalculator.next(r.getInt(IDXFIELD_BEGINLINE), r.getInt(IDXFIELD_BEGINCOLUMN));
455
                r.setLong(IDXFIELD_BEGINRECORDPOS, positionCalculator.getColumnPosition());
456
//                System.out.println("RPOS      : " + r.getLong(IDXFIELD_BEGINRECORDPOS));
457
                if(CollectionUtils.isNotEmpty(geomPaths)) {
458
                    for (int i = 0; i < geomPaths.size(); i++) {
459
                        long beginGeomLine = r.getInt(IDXFIELD_BEGINGEOMLINE + i * 6);
460
                        long endGeomLine = r.getInt(IDXFIELD_ENDGEOMLINE + i * 6);
461
                        if (beginGeomLine == 0 || endGeomLine == 0) {
462
                            continue;
463
                        }
464
                        positionCalculator.next(beginGeomLine, r.getInt(IDXFIELD_BEGINGEOMCOLUMN + i * 6));
465
                        r.setLong(IDXFIELD_BEGINGEOMPOS + i * 6, positionCalculator.getColumnPosition());
466
                        positionCalculator.next(endGeomLine, r.getInt(IDXFIELD_ENDGEOMCOLUMN + i * 6));
467
                        r.setLong(IDXFIELD_ENDGEOMPOS + i * 6, positionCalculator.getColumnPosition());
468
//                        System.out.println("GPOS" + i + "     : " + r.getLong(IDXFIELD_BEGINGEOMPOS + i * 6) + " " + r.getLong(IDXFIELD_ENDGEOMPOS + i * 6));
469
                    }
470
                }
471
                theIndex.set(j, r);
472
                if (status != null) {
473
                    if (status.isCancellationRequested()) {
474
                        status.cancel();
475
                        removeIndex(indexFile);
476
                        return;
477
                    }
478
                    status.incrementCurrentValue();
479
                }
480

    
481
            }
482
            this.index = new RecordsFileImpl(indexFile);
483
            if (status != null) {
484
                status.terminate();
485
            }
486
        } catch (UserCancelTaskException ex) {
487
            if (status != null) {
488
                if (status.isCancellationRequested()) {
489
                    status.cancel();
490
                }
491
            }
492
            removeIndex(indexFile);
493
            throw ex;
494
        } catch (Exception ex) {
495
            if (status != null) {
496
                status.abort();
497
            }
498
            removeIndex(indexFile);
499
            throw new IOException("Can't create index " + Objects.toString(indexFile), ex);
500
        } finally {
501
            if (status != null) {
502
                status.pop();
503
            }
504
        }
505
    }
506
    
507
    private void removeIndex(File indexFile) {
508
        indexFile.delete();
509
    }
510

    
511
    private static class CharacterSize {
512

    
513
        private final Charset charset;
514
        private final CharBuffer charBuffer;
515

    
516
        public CharacterSize(Charset charset) {
517
            this.charset = charset;
518
            this.charBuffer = CharBuffer.allocate(1);
519
        }
520

    
521
        public int size(char ch) {
522
            this.charBuffer.put(0, ch);
523
            this.charBuffer.position(0);
524
            ByteBuffer buffer = this.charset.encode(this.charBuffer);
525
            return buffer.limit();
526
        }
527

    
528
        public int size(char[] cbuf, int off, int len) {
529
            CharBuffer cb = CharBuffer.wrap(cbuf, off, len);
530
            ByteBuffer byteBuffer = this.charset.encode(cb);
531
            return byteBuffer.limit();
532
        }
533

    
534
        public int size(char[] cbuf) {
535
            CharBuffer cb = CharBuffer.wrap(cbuf, 0, cbuf.length);
536
            ByteBuffer byteBuffer = this.charset.encode(cb);
537
            return byteBuffer.limit();
538
        }
539

    
540
        public int size(String s) {
541
            CharBuffer cb = CharBuffer.wrap(s);
542
            ByteBuffer byteBuffer = this.charset.encode(cb);
543
            return byteBuffer.limit();
544
        }
545
    }
546

    
547
    private static class PositionCalculator {
548

    
549
        private final RandomAccessFileReader reader;
550
        private final BufferedReader breader;
551
        private long currentPosition;
552
        private long currentColumn;
553
        private long currentLine;
554
        private long currentColumnPosition;
555
        private long currentLinePosition;
556

    
557
        private final char[] ch;
558
        private final CharacterSize characterSize;
559

    
560
        public PositionCalculator(RandomAccessFileReader reader) {
561
            this.reader = reader;
562
            this.breader = new BufferedReader(this.reader, 1024 * 8);
563
            this.currentPosition = this.reader.getCurrentPosition();
564
            this.currentLine = 1;
565
            this.currentColumn = 1;
566
            this.ch = new char[1];
567
            this.characterSize = new CharacterSize(this.reader.getCharset());
568
        }
569

    
570
        public boolean next(long line, long column) throws IOException {
571
//            System.out.println();
572
//            System.out.println("----"+line+" "+column);
573
            if(this.currentLine>line){
574
                throw new IOException("Illegal column number " + column + " ("+this.currentColumn+") for line " + line+ " ("+this.currentLine+")");
575
            }
576
            if(this.currentLine==line && this.currentColumn > column){
577
                throw new IOException("Illegal column number " + column + " ("+this.currentColumn+") for line " + line);
578
            }
579
//            System.out.print(this.currentLine+":");
580
            while (this.currentLine < line) {
581
                if (breader.read(this.ch, 0, 1) < 1) {
582
                    return false;
583
                }
584
                char c = ch[0];
585
//                System.out.print(String.valueOf(c));
586
                this.currentPosition += characterSize.size(c);
587
                if (c == '\n') {
588
                    this.currentLine++;
589
                    this.currentColumn = 1;
590
//                    System.out.print(this.currentLine+":");
591
                }
592
            }
593
            this.currentLinePosition = this.currentPosition;
594
            while (true) {
595
                if (breader.read(this.ch, 0, 1) < 1) {
596
                    return false;
597
                }
598
                char c = ch[0];
599
//                System.out.print(String.valueOf(c));
600
                this.currentColumn++;
601
                this.currentPosition += characterSize.size(c);
602
                if(this.currentColumn >= column){
603
                    break;
604
                }
605
                if (c == '\n') {
606
                    throw new IOException("Illegal column number " + column + " ("+this.currentColumn+") for line " + line+ " ("+this.currentLine+")");
607
                }
608
            }
609
            this.currentColumnPosition = this.currentPosition;
610
//            System.out.println();
611
            return true;
612
        }
613

    
614
        public long getLinePosition() {
615
            return this.currentLinePosition;
616
        }
617

    
618
        public long getColumnPosition() {
619
            return this.currentColumnPosition;
620
        }
621

    
622
    }
623

    
624
    public static void main(String[] args) throws Exception {
625
        new DefaultLibrariesInitializer().fullInitialize();
626

    
627
//        final String XMLFILE1 = "/home/jjdelcerro/datos/geodata/vector/gml/navarra.gml";
628
//        final String XMLFILE2 = "/home/jjdelcerro/datos/geodata/vector/gml/Municipis/Municipis.gml";
629
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/1075305YJ2717N.gml";
630
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/Recinto.gml";
631
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/FG-GML-543863-AdmBdry-20190101-0001.gml";
632
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/Municipis.gml";
633
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/navarra.gml";
634
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/Falls.gml";
635
        
636
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/AerodromeArea.gml";
637
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/AerodromeType.gml"; //No tiene geometr?as
638
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/BuildingP.gml";
639
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/CablewayLink.gml";
640
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/ConditionOfFacility.gml"; //No tiene geometr?as
641
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/CrossingS.gml";
642
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/CrossingP.gml";
643
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/DamOrWeirL.gml";
644
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/EmbankmentL.gml";
645
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/EmbankmentS.gml";
646
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/FordP.gml";
647
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/FormOfWay.gml";
648
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/FunctionalRoadClass.gml"; //No tiene geometr?as
649
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/INSPIRE_GN.gml";
650
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/INSPIRE_AU.gml"; //Hay 3 geometr?as, LineString, Surface y MultiSurface
651
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RunwayArea.gml";
652
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RailwayStationArea.gml";
653
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/DamOrWeirS.gml";
654
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/NominalTrackGauge.gml"; //No tiene geometr?as
655
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/NumberOfTracks.gml"; //No tiene geometr?as
656
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/Road.gml"; //No tiene geometr?as
657
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RoadServiceType.gml"; //No tiene geometr?as
658
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RailwayArea.gml";
659
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RailwayElectrification.gml"; //No tiene geometr?as
660
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RailwayType.gml"; //No tiene geometr?as
661
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RailwayLink.gml"; //Added Multicurve Strategy (ojo, en los registros, tras la geometr?a aparece otro atributo a null
662
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RailwayYardArea.gml";
663
        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RoadArea.gml"; //NO VA
664
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RoadLink.gml"; //Hay 2 geometr?as, Curve y Multicurve
665
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RoadServiceArea.gml";
666
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RoadSurfaceCategory.gml"; //No tiene geometr?as
667
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/RoadWidth.gml"; //No tiene geometr?as
668
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/ShorelineConstructionL.gml";
669
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/StandingWater.gml";
670
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/SurfaceComposition.gml";
671
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/VerticalPosition.gml"; //No tiene geometr?as
672
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/Watercourse.gml"; //Hay 2 geometr?as, Curve y Multicurve
673
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/WatercourseLink.gml";
674
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/WatercourseLinkSequence.gml"; //No tiene geometr?as
675
//        final String XMLFILE1 = "/home/fdiaz/projects/GMLS/sk/Wetland.gml";
676

    
677
        
678

    
679

    
680

    
681

    
682

    
683
        String gmlfile = XMLFILE1;
684
        File idxFile = new File(FilenameUtils.removeExtension(gmlfile)+".gmlidx");
685
        if(idxFile.exists()){
686
            idxFile.delete();
687
        }
688
        File gfsFile = new File(FilenameUtils.removeExtension(gmlfile)+".gfs");
689
        if(gfsFile.exists()){
690
            gfsFile.delete();
691
        }
692
        GfsFile gfs = new GfsFile();
693
        gfs.fetch(new File(gmlfile));
694
        gfs.save(gfsFile);
695
//        return;
696
        XMLFileAsList gml = new XMLFileAsList(
697
                new File(gmlfile), 
698
//                StandardCharsets.ISO_8859_1, 
699
                StandardCharsets.UTF_8, 
700
                gfs.getBaseElementPath(),
701
                gfs.getGeometryElementPaths(),
702
                gfs.getPropertiesPaths()
703
        );
704
        gml.createIndex(new File(FilenameUtils.removeExtension(gmlfile)+".gmlidx"), SimpleTaskStatus.FAKE_STATUS);
705
        System.out.println("File: "+gmlfile);
706
        for (int i = 0; i < gml.size(); i++) {
707
            List<String> item = gml.get(i);
708
            System.out.println("RECORD "+i+":"+item);
709
        }
710
        System.out.println(StringUtils.join(gfs.getPropertiesPaths(), "\n"));
711
        System.out.println("Geometries:\n"+StringUtils.join(gfs.getGeometryElementPaths(), "\n"));
712
    }
713
}