Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.impl / src / main / java / org / gvsig / fmap / dal / feature / paging / impl / FeaturePagingHelperImpl.java @ 42775

History | View | Annotate | Download (24.5 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.fmap.dal.feature.paging.impl;
25

    
26
import java.util.Collection;
27
import java.util.Iterator;
28
import java.util.List;
29
import java.util.ListIterator;
30
import org.slf4j.Logger;
31
import org.slf4j.LoggerFactory;
32

    
33
import org.gvsig.fmap.dal.exception.DataException;
34
import org.gvsig.fmap.dal.feature.EditableFeature;
35
import org.gvsig.fmap.dal.feature.Feature;
36
import org.gvsig.fmap.dal.feature.FeatureQuery;
37
import org.gvsig.fmap.dal.feature.FeatureSelection;
38
import org.gvsig.fmap.dal.feature.FeatureSet;
39
import org.gvsig.fmap.dal.feature.FeatureStore;
40
import org.gvsig.fmap.dal.feature.FeatureType;
41
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
42
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException;
43
import org.gvsig.fmap.dal.feature.impl.dynobjectutils.DynObjectFeatureFacade;
44
import org.gvsig.fmap.dal.feature.paging.FacadeOfAFeaturePagingHelper;
45
import org.gvsig.fmap.dal.feature.paging.FeaturePagingHelper;
46
import org.gvsig.tools.dynobject.DynObject;
47
import org.gvsig.tools.dynobject.DynObjectSet;
48
import org.gvsig.tools.dynobject.impl.DefaultDynObjectPagingHelper;
49
import org.gvsig.tools.exception.BaseException;
50
import org.gvsig.tools.visitor.VisitCanceledException;
51
import org.gvsig.tools.visitor.Visitor;
52

    
53
/**
54
 * Helper class to access the values of a FeatureCollection by position. Handles
55
 * pagination automatically to avoid filling the memory in case of big
56
 * collections.
57
 *
58
 * TODO: evaluate if its more convenient to read values in the background when
59
 * the returned value is near the end of the page, instead of loading a page on
60
 * demand.
61
 *
62
 * @author gvSIG Team
63
 */
64
public class FeaturePagingHelperImpl extends DefaultDynObjectPagingHelper
65
    implements FeaturePagingHelper {
66

    
67
    private static final Logger LOG = LoggerFactory
68
        .getLogger(FeaturePagingHelperImpl.class);
69

    
70
    private FeatureQuery query;
71

    
72
    private FeatureStore featureStore;
73

    
74
    /** If the selected Features must be returned as the first ones. **/
75
    private boolean selectionUp = false;
76

    
77
    private FeatureSet featSet = null;
78
    private FeatureSelection initialSelection = null;
79

    
80
    private Feature[] features = null;
81

    
82
    private boolean initialization_completed = false;
83
    /**
84
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
85
     *
86
     * @param featureStore
87
     *            to extract data from
88
     * @throws DataException
89
     *             if there is an error initializing the helper
90
     */
91
    public FeaturePagingHelperImpl(FeatureStore featureStore)
92
        throws BaseException {
93
        this(featureStore, DEFAULT_PAGE_SIZE);
94
    }
95

    
96
    /**
97
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
98
     *
99
     * @param featureStore
100
     *            to extract data from
101
     * @param pageSize
102
     *            the number of elements per page data
103
     * @throws DataException
104
     *             if there is an error initializing the helper
105
     */
106
    public FeaturePagingHelperImpl(FeatureStore featureStore, int pageSize)
107
        throws BaseException {
108
        this(featureStore, null, pageSize);
109
    }
110

    
111
    /**
112
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
113
     *
114
     * @param featureStore
115
     *            to extract data from
116
     * @throws DataException
117
     *             if there is an error initializing the helper
118
     */
119
    public FeaturePagingHelperImpl(FeatureStore featureStore,
120
        FeatureQuery featureQuery) throws BaseException {
121
        this(featureStore, featureQuery, DEFAULT_PAGE_SIZE);
122
    }
123

    
124
    /**
125
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
126
     *
127
     * @param featureSet
128
     *            to extract data from
129
     * @param pageSize
130
     *            the number of elements per page data
131
     * @throws DataException
132
     *             if there is an error initializing the helper
133
     */
134
    public FeaturePagingHelperImpl(FeatureStore featureStore,
135
        FeatureQuery featureQuery, int pageSize) throws BaseException {
136
        super();
137
        FeatureQuery query = featureQuery;
138
        if (featureQuery == null) {
139
            query = featureStore.createFeatureQuery();
140
            query.setFeatureType(featureStore.getDefaultFeatureType());
141
        }
142

    
143
        this.featureStore = featureStore;
144
        this.query = query;
145
        this.query.setPageSize(pageSize);
146

    
147
        setDefaultCalculator(new Sizeable() {
148
            public long getSize() {
149
                    FeatureSet featureSet = getFeatureSet(false);
150
                try {
151
                                        return featureSet.getSize();
152
                } catch (BaseException e) {
153
                    LOG.error("Error getting the size of the FeatureSet: "
154
                        + featureSet, e);
155
                    return 0l;
156
                }
157
            }
158
        }, pageSize);
159

    
160

    
161
        if (LOG.isDebugEnabled()) {
162

    
163
            LOG.debug("FeaturePagingHelperImpl created with {} pages, "
164
                + "and a page size of {}", new Long(getCalculator()
165
                .getNumPages()), new Integer(pageSize));
166
        }
167
        this.initialization_completed = true;
168
    }
169

    
170
    /**
171
     * @return the selectionUp status
172
     */
173
    public boolean isSelectionUp() {
174
        return selectionUp;
175
    }
176

    
177
    public void setSelectionUp(boolean selectionUp) {
178
        this.selectionUp = selectionUp;
179
        try {
180
            FeatureSelection currentSelection = getFeatureStore().getFeatureSelection();
181
            if (selectionUp && !currentSelection.isEmpty()) {
182
                initialSelection =(FeatureSelection) currentSelection.clone();
183
                setCalculator(new OneSubsetOneSetPagingCalculator(
184
                    new FeatureSetSizeableDelegate(initialSelection),
185
                    new FeatureSetSizeableDelegate(getFeatureSet(false)),
186
                    getMaxPageSize()));
187
            } else {
188
                if (initialSelection != null) {
189
                    initialSelection.dispose();
190
                    initialSelection = null;
191
                }
192
                setDefaultCalculator(new FeatureSetSizeableDelegate(
193
                    getFeatureSet(false)), getMaxPageSize());
194
            }
195
        } catch (BaseException e) {
196
            LOG.error("Error setting the selection up setting to: "
197
                + selectionUp, e);
198
        } catch (CloneNotSupportedException e) {
199
            LOG.error("Error cloning the selection "
200
                + "while setting the selection up", e);
201
        }
202
    }
203

    
204
    public Feature getFeatureAt(long index) throws BaseException {
205
        // Check if we have currently loaded the viewed page data,
206
        // or we need to load a new one
207
        long pageForIndex = (long) Math.floor(index / getMaxPageSize());
208

    
209
        if (pageForIndex != getCurrentPage()) {
210
            setCurrentPage(pageForIndex);
211
        }
212

    
213
        long positionForIndex = index - (getCurrentPage() * getMaxPageSize());
214

    
215
        if (positionForIndex >= getCurrentPageFeatures().length) {
216
            throw new FeatureIndexException(
217
                new IndexOutOfBoundsException("positionForIndex too big: "
218
                    + positionForIndex));
219
        } else {
220
            Feature feature = getCurrentPageFeatures()[(int) positionForIndex];
221
            return feature;
222
        }
223

    
224
    }
225

    
226
    public Feature[] getCurrentPageFeatures() {
227
        if( this.features==null ) {
228
            try {
229
                this.loadCurrentPageData();
230
            } catch (BaseException ex) {
231
                // Do nothing
232
            }
233
            if( this.features == null ) {
234
                String msg = "Can't retrieve the features from current page.";
235
                LOG.warn(msg);
236
                throw new RuntimeException(msg);
237
            }
238
        }
239
        return features;
240
    }
241

    
242
    /**
243
     * Gets the feature set.
244
     * The boolean tells whether we must create the featureset
245
     * again (for example perhaps we need it after a feature
246
     * has been added/removed)
247
     */
248
    private FeatureSet getFeatureSet(boolean reset) {
249

    
250
        if (featSet == null || reset) {
251

    
252
            if (featSet != null) {
253
                try {
254
                    featSet.dispose();
255
                } catch (Exception ex) {
256
                    LOG.info("Error while disposing featset.", ex);
257
                }
258
            }
259

    
260
            try {
261
                FeatureStore featureStore = getFeatureStore();
262
                synchronized (featureStore) {
263
                    featSet = featureStore.getFeatureSet(getFeatureQuery());
264
                }
265
            } catch (DataException e) {
266
                throw new RuntimeException("Error getting a feature set with the query " + getFeatureQuery());
267
            }
268
        }
269
        return featSet;
270
    }
271

    
272
    public DynObjectSet getDynObjectSet() {
273
            return getFeatureSet(false).getDynObjectSet();
274
    }
275

    
276
    public void reloadCurrentPage() throws BaseException {
277

    
278
        boolean sel_up = this.isSelectionUp();
279

    
280
        setSelectionUp(false);
281
        if (getCalculator().getCurrentPage() > -1) {
282
            loadCurrentPageData();
283
        }
284

    
285
        if (sel_up) {
286
            setSelectionUp(true);
287
        }
288
    }
289

    
290
    public void reload() throws BaseException {
291

    
292
        /*
293
         * Force re-creation of feature set
294
         */
295
        this.getFeatureSet(true);
296

    
297

    
298
        setDefaultCalculator(new Sizeable() {
299
            public long getSize() {
300
                    FeatureSet featureSet = getFeatureSet(false);
301
                try {
302
                                        return featureSet.getSize();
303
                } catch (BaseException e) {
304
                    LOG.error("Error getting the size of the FeatureSet: "
305
                        + featureSet, e);
306
                    return 0l;
307
                }
308
            }
309
        }, getCalculator().getMaxPageSize());
310
        reloadCurrentPage();
311
    }
312

    
313
    public FeatureStore getFeatureStore() {
314
        return featureStore;
315
    }
316

    
317
    public FeatureQuery getFeatureQuery() {
318
        return query;
319
    }
320

    
321
    /**
322
     * Loads all the Features of the current page.
323
     */
324
    protected void loadCurrentPageData() throws BaseException {
325
        if( !initialization_completed ) {
326
            return;
327
        }
328
        final int currentPageSize = getCalculator().getCurrentPageSize();
329
        final Feature[] values = new Feature[currentPageSize];
330

    
331
        long t1 = 0;
332
        if (LOG.isTraceEnabled()) {
333
            t1 = System.currentTimeMillis();
334
        }
335

    
336
        if (selectionUp) {
337
            loadCurrentPageDataWithSelectionUp(values);
338
        } else {
339
            loadCurrentPageDataNoSelection(values);
340
        }
341

    
342
        if (LOG.isTraceEnabled()) {
343
            long t2 = System.currentTimeMillis();
344
            LOG.trace("Time to load {} features: {} ms", new Integer(
345
                currentPageSize), new Long(t2 - t1));
346
        }
347

    
348
        this.features = values;
349
    }
350

    
351
    private void loadCurrentPageDataWithSelectionUp(final Feature[] values)
352
            throws BaseException {
353
        FeatureSelection selection = initialSelection;
354
        if (selection == null) {
355
            loadCurrentPageDataNoSelection(values);
356
        } else {
357
            FeatureSet set = getFeatureSet(false);
358
            try {
359
                OneSubsetOneSetPagingCalculator twoSetsCalculator = null;
360
                if (getCalculator() instanceof OneSubsetOneSetPagingCalculator) {
361
                    twoSetsCalculator
362
                            = (OneSubsetOneSetPagingCalculator) getCalculator();
363
                } else {
364
                    twoSetsCalculator
365
                            = new OneSubsetOneSetPagingCalculator(
366
                                    new FeatureSetSizeableDelegate(selection),
367
                                    new FeatureSetSizeableDelegate(set),
368
                                    getMaxPageSize(), getCalculator().getCurrentPage());
369
                    setCalculator(twoSetsCalculator);
370
                }
371

    
372
                // First load values from the selection, if the current page has
373
                // elements from it
374
                if (twoSetsCalculator.hasCurrentPageAnyValuesInFirstSet()) {
375
                    loadDataFromFeatureSet(values, 0, selection,
376
                            twoSetsCalculator.getFirstSetInitialIndex(),
377
                            twoSetsCalculator.getFirstSetHowMany(), null);
378
                }
379
                // Next, load values from the FeatureSet if the current page has values
380
                // from it
381
                if (twoSetsCalculator.hasCurrentPageAnyValuesInSecondSet()) {
382
                    loadDataFromFeatureSet(
383
                            values,
384
                            // The cast will work as that size will be <= maxpagesize,
385
                            // which is an int
386
                            (int) twoSetsCalculator.getFirstSetHowMany(), set,
387
                            twoSetsCalculator.getSecondSetInitialIndex(),
388
                            twoSetsCalculator.getSecondSetHowMany(), selection);
389
                }
390
            } finally {
391
                /*
392
                 * This is the feature set
393
                 * we dont want to lose it
394
                 */
395
                // set.dispose();
396
            }
397
        }
398
    }
399

    
400
    private void loadCurrentPageDataNoSelection(final Feature[] values)
401
        throws BaseException {
402

    
403
        long firstPosition = getCalculator().getInitialIndex();
404

    
405
        if (LOG.isDebugEnabled()) {
406
            LOG.debug("Loading {} Features starting at position {}",
407
                new Integer(getCalculator().getCurrentPageSize()), new Long(
408
                    firstPosition));
409
        }
410

    
411
        FeatureSet featureSet = getFeatureSet(false);
412
        try {
413
                loadDataFromFeatureSet(values, 0, featureSet, firstPosition,
414
                                getCalculator().getCurrentPageSize(), null);
415
        } catch(DataException ex) {
416
            throw ex;
417
            // } finally {
418
                // featureSet.dispose();
419
        }
420

    
421
    }
422

    
423
    private void loadDataFromFeatureSet(final Feature[] values,
424
        final int valuesPosition, FeatureSet set, long initialIndex,
425
        final long howMany, final FeatureSelection selectedFeaturesToSkip)
426
        throws DataException {
427

    
428
        try {
429
            set.accept(new Visitor() {
430

    
431
                private int i = valuesPosition;
432

    
433
                public void visit(Object obj) throws VisitCanceledException,
434
                    BaseException {
435
                    if (i >= valuesPosition + howMany) {
436
                        throw new VisitCanceledException();
437
                    }
438
                    Feature current = (Feature) obj;
439
                    // Add the current Feature only if we don't skip selected
440
                    // features or the feature is not selected
441
                    if (selectedFeaturesToSkip == null
442
                        || !selectedFeaturesToSkip.isSelected(current)) {
443
                        try {
444
                            values[i] = current.getCopy();
445
                            i++;
446
                        } catch(Exception ex) {
447
                            // Aqui no deberia petar, pero...
448
                            // me he encontrado un caso que tenia una referencia a
449
                            // una feature seleccionada que ya no existia. No se como
450
                            // habia pasado, se habia quedado de antes guardada en el
451
                            // proyecto pero la feature ya no existia, y eso hacia que
452
                            // petase al intentar leer de disco la feature a partir
453
                            // de una referencia no valida.
454
                        }
455
                    }
456
                }
457
            }, initialIndex);
458
        } catch (BaseException e) {
459
            if (e instanceof DataException) {
460
                throw ((DataException) e);
461
            } else {
462
                LOG.error("Error loading the data starting at position {}",
463
                    new Long(initialIndex), e);
464
            }
465
        }
466
    }
467

    
468
    public void delete(Feature feature) throws BaseException {
469
        featureStore.delete(feature);
470
        /*
471
         * Force re-creation of feature set
472
         */
473
        this.getFeatureSet(true);
474

    
475
        reloadCurrentPage();
476
    }
477

    
478
    public void insert(EditableFeature feature) throws BaseException {
479
            featureStore.insert(feature);
480
        /*
481
         * Force re-creation of feature set
482
         */
483
        this.getFeatureSet(true);
484

    
485
        reloadCurrentPage();
486
    }
487

    
488
    public void update(EditableFeature feature) throws BaseException {
489
            featureStore.update(feature);
490
        /*
491
         * Force re-creation of feature set
492
         */
493
        this.getFeatureSet(true);
494

    
495
        reloadCurrentPage();
496
    }
497

    
498
    public FeatureType getFeatureType() {
499

    
500
        FeatureType ft = null;
501

    
502
        try {
503
            ft = featureStore.getDefaultFeatureType();
504
        } catch (DataException e) {
505
            LOG.error("Error while getting feature type: " +
506
                e.getMessage(), e);
507
        }
508
        return ft;
509

    
510
        /*
511
         *
512
        FeatureSet featureSet = getFeatureSet();
513
        try {
514
            return featureSet.getDefaultFeatureType();
515
        } finally {
516
            featureSet.dispose();
517
        }
518
        */
519

    
520

    
521
    }
522

    
523
    protected void doDispose() throws BaseException {
524
        initialSelection.dispose();
525
        if (featSet != null) {
526
            try {
527
                featSet.dispose();
528
            } catch (Exception ex) {
529
                LOG.info("Error while disposing featset.", ex);
530
            }
531
        }
532
    }
533

    
534
    public DynObject[] getCurrentPageDynObjects() {
535
        Feature[] features = getCurrentPageFeatures();
536
        DynObject[] dynobjects = new DynObject[features.length];
537
        for (int i = 0; i < dynobjects.length; i++) {
538
            dynobjects[i] = new DynObjectFeatureFacade(features[i]);
539
        }
540
        return dynobjects;
541
    }
542

    
543
    public DynObject getDynObjectAt(long index) throws BaseException {
544
        return new DynObjectFeatureFacade(getFeatureAt(index));
545
    }
546

    
547
    public List asList() {
548
        return new FeaturePagingHelperList();
549
    }
550

    
551
    public List asListOfDynObjects() {
552
        return new DynObjectPagingHelperList();
553
    }
554

    
555
    private class FeaturePagingHelperList extends PagingHelperList {
556
        public Object get(int i) {
557
            try {
558
                return getFeatureAt(i);
559
            } catch (BaseException ex) {
560
                throw  new RuntimeException(ex);
561
            }
562
        }
563
    }
564

    
565
    private class DynObjectPagingHelperList extends PagingHelperList {
566
        public Object get(int i) {
567
            try {
568
                return getDynObjectAt(i);
569
            } catch (BaseException ex) {
570
                throw  new RuntimeException(ex);
571
            }
572
        }
573

    
574
    }
575

    
576
    private abstract class PagingHelperList implements List,  FacadeOfAFeaturePagingHelper {
577

    
578
        @Override
579
        public FeaturePagingHelper getFeaturePagingHelper() {
580
            return FeaturePagingHelperImpl.this;
581
        }
582
        
583
        public int size() {
584
            try {
585
                return (int) getFeatureSet(false).getSize();
586
            } catch (DataException ex) {
587
                throw  new RuntimeException(ex);
588
            }
589
        }
590

    
591
        public boolean isEmpty() {
592
            try {
593
                return getFeatureSet(false).isEmpty();
594
            } catch (DataException ex) {
595
                throw  new RuntimeException(ex);
596
            } catch (ConcurrentDataModificationException ex) {
597
                LOG.warn(
598
                    "Error to asking about the emptiness of the store. Retrying reloading data.",
599
                    ex);
600
                try {
601
                    reload();
602
                } catch (BaseException e) {
603
                    LOG.warn("Error reloading data.", e);
604
                    throw new RuntimeException(e);
605
                }
606
                try {
607
                    return getFeatureSet(false).isEmpty();
608
                } catch (DataException e) {
609
                    LOG.warn(
610
                        "Error to asking about the emptiness of the store after reloading data.",
611
                        e);
612
                    throw new RuntimeException(e);
613
                }
614
            }
615
        }
616

    
617
        public Iterator iterator() {
618
            try {
619
                return getFeatureSet(false).fastIterator();
620
            } catch (DataException ex) {
621
                throw  new RuntimeException(ex);
622
            }
623
        }
624

    
625
        public boolean contains(Object o) {
626
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
627
        }
628

    
629
        public Object[] toArray() {
630
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
631
        }
632

    
633
        public Object[] toArray(Object[] ts) {
634
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
635
        }
636

    
637
        public boolean add(Object e) {
638
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
639
        }
640

    
641
        public boolean remove(Object o) {
642
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
643
        }
644

    
645
        public boolean containsAll(Collection clctn) {
646
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
647
        }
648

    
649
        public boolean addAll(Collection clctn) {
650
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
651
        }
652

    
653
        public boolean addAll(int i, Collection clctn) {
654
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
655
        }
656

    
657
        public boolean removeAll(Collection clctn) {
658
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
659
        }
660

    
661
        public boolean retainAll(Collection clctn) {
662
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
663
        }
664

    
665
        public void clear() {
666
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
667
        }
668

    
669
        public Object set(int i, Object e) {
670
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
671
        }
672

    
673
        public void add(int i, Object e) {
674
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
675
        }
676

    
677
        public Object remove(int i) {
678
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
679
        }
680

    
681
        public int indexOf(Object o) {
682
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
683
        }
684

    
685
        public int lastIndexOf(Object o) {
686
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
687
        }
688

    
689
        public ListIterator listIterator() {
690
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
691
        }
692

    
693
        public ListIterator listIterator(int i) {
694
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
695
        }
696

    
697
        public List subList(int i, int i1) {
698
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
699
        }
700

    
701
    }
702
}