Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libUI / src / org / gvsig / gui / beans / swing / jComboBoxItemsSeeker / ComboBoxSingularItemsSeekerConfigurableModel.java @ 10413

History | View | Annotate | Download (17.4 KB)

1
package org.gvsig.gui.beans.swing.jComboBoxItemsSeeker;
2

    
3
import java.util.Arrays;
4
import java.util.Collections;
5
import java.util.List;
6
import java.util.TreeSet;
7
import java.util.Vector;
8

    
9

    
10
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
11
 *
12
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
13
 *
14
 * This program is free software; you can redistribute it and/or
15
 * modify it under the terms of the GNU General Public License
16
 * as published by the Free Software Foundation; either version 2
17
 * of the License, or (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
27
 *
28
 * For more information, contact:
29
 *
30
 *  Generalitat Valenciana
31
 *   Conselleria d'Infraestructures i Transport
32
 *   Av. Blasco Ib??ez, 50
33
 *   46010 VALENCIA
34
 *   SPAIN
35
 *
36
 *      +34 963862235
37
 *   gvsig@gva.es
38
 *      www.gvsig.gva.es
39
 *
40
 *    or
41
 *
42
 *   IVER T.I. S.A
43
 *   Salamanca 50
44
 *   46005 Valencia
45
 *   Spain
46
 *
47
 *   +34 963163400
48
 *   dac@iver.es
49
 */
50

    
51

    
52
/**
53
 * This class inherits of 'AbstractDefaultComboBoxItemsSeekerConfigurableModel' and it's optimized for not repetead items: and if there are repeated
54
 *    items this would it will work badly; if there are repeated items use 'ComboBoxItemsSeekerConfigurableModel'.  
55
 *    
56
 * Limitations: This model works badly if has repeated items.
57
 * 
58
 *  @author Pablo Piqueras Bartolom? (p_queras@hotmail.com)
59
 */
60
public class ComboBoxSingularItemsSeekerConfigurableModel extends AbstractDefaultComboBoxItemsSeekerConfigurableModel implements java.io.Serializable {
61
        private static final long serialVersionUID = -2442496446788716549L;
62
        
63
        // INNER MODEL STRUCTURES
64
        private TreeSet itemsShowed;
65
        // END INNER MODEL STRUCTURES
66
        
67
        // OTHER FLAGS
68
        protected boolean thisIsAComboBoxSingularItemsSeekerConfigurableModelClassInialized = false; // To distinguish the class which invokes some methods of this class
69
        // END OTHER FLAGS
70
        
71
        /**
72
         * Default constructor without parameters
73
         * 
74
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#AbstractDefaultComboBoxItemsSeekerConfigurableModel() 
75
         */
76
        public ComboBoxSingularItemsSeekerConfigurableModel() {
77
                super();
78
                this.initialize();
79
        }
80

    
81
        /**
82
         * Default constructor with an array as a parameter
83
         * 
84
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#AbstractDefaultComboBoxItemsSeekerConfigurableModel(Object[]) 
85
         */
86
        public ComboBoxSingularItemsSeekerConfigurableModel(Object[] items) {
87
                super(items);
88
                this.initialize();
89
                this.itemsShowed.addAll(Arrays.asList(items));
90
        }
91

    
92
        /**
93
         * Default constructor with a Vector as a parameter
94
         * 
95
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#AbstractDefaultComboBoxItemsSeekerConfigurableModel(Vector) 
96
         */
97
        public ComboBoxSingularItemsSeekerConfigurableModel(Vector objects) {
98
                super(objects);
99
                this.initialize();
100
                this.itemsShowed.addAll(objects);
101
        }
102
        
103
        /*
104
         * (non-Javadoc)
105
         * @see org.gvsig.gui.beans.swing.jComboBoxItemsSeeker.AbstractDefaultComboBoxItemsSeekerConfigurableModel#initialize()
106
         */
107
        protected void initialize() {
108
                super.initialize();
109
                logger.debug("Se ejecuta el initialize del hijo");
110
                
111
                thisIsAComboBoxSingularItemsSeekerConfigurableModelClassInialized = true;
112
                this.itemsShowed = new TreeSet();
113
        }
114
        
115
        
116
        
117
        ////// REIMPLEMENTATION OF SOME METHODS OF "DefaultComboBoxModel" TO ADAPT THE BEHAVIOR OF THIS MODEL //////
118
        
119
        /*
120
         *  (non-Javadoc)
121
         * @see org.gvsig.gui.beans.swing.jComboBoxItemsSeeker.AbstractDefaultComboBoxItemsSeekerConfigurableModel#addElement(java.lang.Object)
122
         */
123
        public void addElement(Object anObject) {
124
                super.addElementToParent(anObject); // this adds the element and selects by default the first item added
125
                
126
                // Add the item also in the inner attribute
127
                this.itemsShowed.add(anObject);
128

    
129
                this.reset();
130
        }
131
        
132
        /*
133
         *  (non-Javadoc)
134
         * @see org.gvsig.gui.beans.swing.jComboBoxItemsSeeker.AbstractDefaultComboBoxItemsSeekerConfigurableModel#getElementAt(int)
135
         */
136
        public Object getElementAt(int index) {
137
                if (!this.thisIsAComboBoxSingularItemsSeekerConfigurableModelClassInialized)
138
                        return super.getParentElementAt(index);
139
                
140
                if (this.startState) // At the beginning shows all items
141
                {                        
142
                        switch(this.getStartBehavior())
143
                        {
144
                                case MAINTAIN_ORIGINAL_POSITION_START :                                
145
                                        return super.getParentElementAt(index);
146
                                case ORDERED_START :
147
                                        // If the items aren't sorted -> sort them!
148
                                        if ((!this.itemsInTheArray) || (this.stateAllItems != STATE_ITEMS_ARE_ORDERED))
149
                                                this.setItemsCopyToArray();
150
                                        
151
                                        // Return the item at that position
152
                                        return this.itemsSearchesShow[index];
153
                                case DISORDERED_START :
154
                                        
155
                                        if (!this.itemsInTheArray)
156
                                                this.setItemsCopyToArray();
157
                                        
158
                                        // If the items aren't disordered -> sort them!
159
                                        if (this.stateAllItems != STATE_ITEMS_ARE_DISORDERED)
160
                                                this.disorderItemsCopy();
161

    
162
                                        // Return the item at that position
163
                                        return this.itemsSearchesShow[index];
164
                                default:
165
                                        // If error configuration -> it gives back an empty object for not to produce more errors 
166
                                        return new Object();
167
                        }
168
                }
169
                else
170
                {                        
171
                        switch(this.getSearchBehavior())
172
                        {
173
                                case MAINTAIN_ORIGINAL_POSITION_ALL_ITEMS_SEARCH :
174
                                        return super.getParentElementAt(index);
175
                                case ORDERED_ALL_ITEMS_SEARCH :
176
                                        if ((!this.itemsInTheArray) || (this.stateAllItems != STATE_ITEMS_ARE_ORDERED))
177
                                                this.setItemsCopyToArray();
178
                                        return this.itemsSearchesShow[index];
179
                                case DISORDERED_ALL_ITEMS_SEARCH :
180
                                        if (!this.itemsInTheArray)
181
                                                this.setItemsCopyToArray();
182

    
183
                                        // If the items aren't sorted -> sort them!
184
                                        if (this.stateAllItems != STATE_ITEMS_ARE_DISORDERED)
185
                                                this.disorderItemsCopy();
186
                                        return this.itemsSearchesShow[index];
187
                                case MAINTAIN_ORIGINAL_POSITION_DYNAMIC_SEARCH : case ORDERED_DYNAMIC_SEARCH : case DISORDERED_DYNAMIC_SEARCH :
188
                                        if (!this.itemsInTheArray)
189
                                                this.setItemsCopyToArray();
190

    
191
                                        if (!this.dynamicSearchDone)
192
                                                seekDynamicItems();
193
                                        
194
                                        return this.itemsSearchesShow[index];
195
                                default:
196
                                        // If error configuration -> it gives back an empty object for not to produce more errors 
197
                                        return new Object();
198
                        }
199
                }                
200
        }
201

    
202
        /*
203
         *  (non-Javadoc)
204
         * @see org.gvsig.gui.beans.swing.jComboBoxItemsSeeker.AbstractDefaultComboBoxItemsSeekerConfigurableModel#getIndexOf(java.lang.Object)
205
         */
206
        public int getIndexOf(Object anObject) {
207
                if (!this.thisIsAComboBoxSingularItemsSeekerConfigurableModelClassInialized)
208
                        return super.getParentIndexOf(anObject);
209
                
210
                if (!this.itemsInTheArray)
211
                {
212
                        if (this.startState) // At the beginning shows all items
213
                        {                        
214
                                switch(this.getStartBehavior())
215
                                {
216
                                        case MAINTAIN_ORIGINAL_POSITION_START : // Do nothing        
217
                                                break;
218
                                        case ORDERED_START :
219
                                                this.setItemsCopyToArray();
220
                                                break;
221
                                        case DISORDERED_START :
222
                                                if (!this.itemsInTheArray)
223
                                                        this.setItemsCopyToArray();
224
                                                
225
                                                // If the items aren't disordered -> sort them!
226
                                                if (this.stateAllItems != STATE_ITEMS_ARE_DISORDERED)
227
                                                        this.disorderItemsCopy();
228

    
229
                                                break;
230
                                        default:
231
                                                // If error configuration -> it gives back -1 for not to produce more errors 
232
                                                return -1;
233
                                }
234
                        }
235
                        else
236
                        {                        
237
                                switch(this.getSearchBehavior())
238
                                {
239
                                        case MAINTAIN_ORIGINAL_POSITION_ALL_ITEMS_SEARCH : // Do nothing        
240
                                                break;
241
                                        case ORDERED_ALL_ITEMS_SEARCH :
242
                                                if ((!this.itemsInTheArray) || (this.stateAllItems != STATE_ITEMS_ARE_ORDERED))
243
                                                        this.setItemsCopyToArray();
244
                                                break;
245
                                        case DISORDERED_ALL_ITEMS_SEARCH :
246
                                                if (!this.itemsInTheArray)
247
                                                        this.setItemsCopyToArray();
248

    
249
                                                // If the items aren't disordered -> sort them!
250
                                                if (this.stateAllItems != STATE_ITEMS_ARE_DISORDERED)
251
                                                        this.disorderItemsCopy();
252

    
253
                                                break;
254
                                        case MAINTAIN_ORIGINAL_POSITION_DYNAMIC_SEARCH : case ORDERED_DYNAMIC_SEARCH : case DISORDERED_DYNAMIC_SEARCH :
255
                                                if (!this.itemsInTheArray)
256
                                                        this.setItemsCopyToArray();
257

    
258
                                                if (!this.dynamicSearchDone)
259
                                                        seekDynamicItems();
260
                                                
261
                                                break;
262
                                        default:
263
                                                // If error configuration -> it gives back -1 for not to produce more errors 
264
                                                return -1;
265
                                }
266
                        }                
267
                        
268
                }
269

    
270
                if (((this.startState) && (this.getStartBehavior() == MAINTAIN_ORIGINAL_POSITION_START)) || ((!this.startState) && (this.getSearchBehavior() == MAINTAIN_ORIGINAL_POSITION_ALL_ITEMS_SEARCH)))
271
                        return super.getParentIndexOf(anObject); //this.itemsShowed.indexOf(anObject);
272
                else
273
                        return (Arrays.asList(this.itemsSearchesShow)).indexOf(anObject);
274

    
275
        }
276

    
277
        /*
278
         *  (non-Javadoc)
279
         * @see org.gvsig.gui.beans.swing.jComboBoxItemsSeeker.AbstractDefaultComboBoxItemsSeekerConfigurableModel#getSize()
280
         */
281
        public int getSize() {
282
                if (!this.thisIsAComboBoxSingularItemsSeekerConfigurableModelClassInialized)
283
                        return super.getParentSize();
284
                
285
                if (this.startState)
286
                        return this.itemsShowed.size();                        
287
                
288
                switch(this.getSearchBehavior())
289
                {
290
                        case MAINTAIN_ORIGINAL_POSITION_ALL_ITEMS_SEARCH: case ORDERED_ALL_ITEMS_SEARCH: case DISORDERED_ALL_ITEMS_SEARCH:
291
                                return this.itemsShowed.size();
292
                        case MAINTAIN_ORIGINAL_POSITION_DYNAMIC_SEARCH: case ORDERED_DYNAMIC_SEARCH: case DISORDERED_DYNAMIC_SEARCH:
293
                                if (!this.itemsInTheArray)
294
                                        this.setItemsCopyToArray();
295

    
296
                                if (!this.dynamicSearchDone)
297
                                        seekDynamicItems();
298

    
299
                                return this.itemsSearchesShow.length;
300
//                        case ORDERED_DYNAMIC_SEARCH:
301
//                                if (!this.dynamicSearchDone)
302
//                                        seekDynamicItems();
303
//
304
//                                return this.itemsSearchesShow.length;
305
//                        case DISORDERED_DYNAMIC_SEARCH:
306
//                                if (!this.dynamicSearchDone)
307
//                                        seekDynamicItems();
308
//
309
//                                return this.itemsSearchesShow.length;
310
                        default:
311
                                // If error configuration -> it gives back 0 for not to produce more errors 
312
                                return 0;
313
                }
314
        }
315

    
316
        /*
317
         *  (non-Javadoc)
318
         * @see org.gvsig.gui.beans.swing.jComboBoxItemsSeeker.AbstractDefaultComboBoxItemsSeekerConfigurableModel#insertElementAt(java.lang.Object, int)
319
         */
320
        public void insertElementAt(Object anObject, int index) {
321
                super.insertToParentElementAt(anObject, index);
322
                
323
                // Add the item also in the inner attribute
324
                this.itemsShowed.add(anObject);
325

    
326
                this.reset();                
327
        }
328

    
329
        /*
330
         *  (non-Javadoc)
331
         * @see org.gvsig.gui.beans.swing.jComboBoxItemsSeeker.AbstractDefaultComboBoxItemsSeekerConfigurableModel#removeAllElements()
332
         */
333
        public void removeAllElements() {
334
                super.removeAllElementsOfParent();
335
                
336
                // Also empty the inner attribute
337
                itemsShowed.clear();                
338
                
339
                this.reset();        
340
        }
341

    
342
        /*
343
         *  (non-Javadoc)
344
         * @see org.gvsig.gui.beans.swing.jComboBoxItemsSeeker.AbstractDefaultComboBoxItemsSeekerConfigurableModel#removeElement(java.lang.Object)
345
         */
346
        public void removeElement(Object anObject) {
347
                super.removeParentElement(anObject);
348
                
349
                // Remove the object also in the inner attribute
350
                itemsShowed.remove(anObject);
351
                
352
                this.reset();                
353
        }
354

    
355
        /*
356
         *  (non-Javadoc)
357
         * @see org.gvsig.gui.beans.swing.jComboBoxItemsSeeker.AbstractDefaultComboBoxItemsSeekerConfigurableModel#removeElementAt(int)
358
         */
359
        public void removeElementAt(int index) {
360
                Object obj = new Object();
361
                
362
                obj = super.getParentElementAt(index);
363
                super.removeParentElementAt(index);
364
                
365
                // Remove the object also in the inner attribute
366
                itemsShowed.remove(obj);
367
                
368
                this.reset();
369
        }
370

    
371
        ////// END REIMPLEMENTATION OF SOME METHODS OF "DefaultComboBoxModel" TO ADAPT THE BEHAVIOR OF THIS MODEL //////        
372

    
373
        
374
        
375
        ////// OTHER METHODS //////
376
        
377
        /*
378
         *  (non-Javadoc)
379
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#getParentAllData()
380
         */
381
        public Vector getParentAllData()
382
        {
383
                Vector data = new Vector();
384
                int size;
385
                
386
                logger.debug("Parent size: " + super.getParentSize());
387
                logger.debug("ItemsShowed size: " + this.itemsShowed.size());
388
                
389
                // Caso de model que no permite items repetidos con items repetidos
390
                if (this.itemsShowed.size() < super.getParentSize())
391
                        size = super.getParentSize();
392
                else
393
                        size = this.itemsShowed.size();
394
                
395
                for (int i = 0; i < size; i++)
396
                        data.add(super.getParentElementAt(i));
397
                
398
                return data;
399
        }
400
        
401
        /*
402
         *  (non-Javadoc)
403
         * @see org.gvsig.gui.beans.swing.jComboBoxItemsSeeker.AbstractDefaultComboBoxItemsSeekerConfigurableModel#disorderItemsCopy()
404
         */
405
        protected void disorderItemsCopy() {
406
                if (this.getSearchBehavior() == DISORDERED_DYNAMIC_SEARCH)
407
                        Collections.shuffle(Arrays.asList(this.itemsSearchesShow)); // Disorder the items to show
408
                else
409
                {
410
                        this.itemsSearchesShow = this.itemsShowed.toArray();
411
                        Collections.shuffle(Arrays.asList(this.itemsSearchesShow)); // Disorder the items
412
                }
413
                
414
                this.stateAllItems = STATE_ITEMS_ARE_DISORDERED;
415
        }
416

    
417
        /*
418
         *  (non-Javadoc)
419
         * @see org.gvsig.gui.beans.swing.jComboBoxItemsSeeker.AbstractDefaultComboBoxItemsSeekerConfigurableModel#getDynamicItemsSearch(org.gvsig.gui.beans.swing.jComboBoxItemsSeeker.AbstractDefaultComboBoxItemsSeekerConfigurableModel.BinaryRankOfItemsSearch, int, int)
420
         */
421
        protected void getDynamicItemsSearch(BinaryRankOfItemsSeek search, int lowIndex, int hightIndex) {
422
                int lowIndexSubSet2;
423
                int hightIndexSubSet2;
424
                List aux;
425

    
426
                if (isCaseSensitive_Flag())
427
                {
428
                        if (lowIndex <= hightIndex)
429
                        {
430
                                if (hightIndex == (itemsSearchesShow.length - 1))
431
                                {
432
                                        aux = new Vector(hightIndex - lowIndex + 1 , 1); // Parameters: Initial Capacity and 1 -> capacity increment
433
                                        aux.addAll(Arrays.asList((this.itemsShowed.subSet(this.itemsSearchesShow[lowIndex], this.itemsSearchesShow[hightIndex])).toArray()));
434
                                        aux.add(this.itemsSearchesShow[hightIndex]);
435
                                        this.itemsSearchesShow = aux.toArray();
436
                                }
437
                                else
438
                                        this.itemsSearchesShow = (this.itemsShowed.subSet(this.itemsSearchesShow[lowIndex], this.itemsSearchesShow[hightIndex+1])).toArray();
439
                        }
440
                        else // Any items match their start with the written text
441
                                this.itemsSearchesShow = new Object[0];
442
                }
443
                else
444
                {
445
                        lowIndexSubSet2 = search.getLowIndexSecondSubSet();
446
                        hightIndexSubSet2 = search.getHightIndexSecondSubSet();
447
                        
448
                        // If any element has been found
449
                        if ((lowIndex > hightIndex) && (lowIndexSubSet2 > hightIndexSubSet2))
450
                        {
451
                                this.itemsSearchesShow = new Object[0];
452
                                return;
453
                        }
454

    
455
                        aux = new Vector();
456
                        
457
                        // Second Subset (Uppercases are first)
458
                        if (lowIndexSubSet2 <= hightIndexSubSet2)
459
                        {
460
                                if ((lowIndex != lowIndexSubSet2) && (hightIndex != hightIndexSubSet2))
461
                                {
462
                                        aux.addAll(Arrays.asList((this.itemsShowed.subSet(this.itemsSearchesShow[lowIndexSubSet2], this.itemsSearchesShow[hightIndexSubSet2])).toArray()));
463
                                        aux.add(this.itemsSearchesShow[hightIndexSubSet2]);
464
                                }
465
                        }
466
        
467
                        // First Subset (Uppercases are first)
468
                        if (lowIndex <= hightIndex)
469
                        {
470
                                aux.addAll(Arrays.asList((this.itemsShowed.subSet(this.itemsSearchesShow[lowIndex], this.itemsSearchesShow[hightIndex])).toArray()));
471
                                aux.add(this.itemsSearchesShow[hightIndex]);
472
                        }
473
                        
474
                        this.itemsSearchesShow = aux.toArray();
475
                }                
476
        }
477

    
478

    
479
        /*
480
         *  (non-Javadoc)
481
         * @see org.gvsig.gui.beans.swing.jComboBoxItemsSeeker.AbstractDefaultComboBoxItemsSeekerConfigurableModel#seekDynamicItems()
482
         */
483
        protected void seekDynamicItems() {
484
                int lowIndex;
485
                int hightIndex;
486
                
487
                // If doesn't have to seek items -> finish
488
                if (this.writtenText.compareTo("") == 0)
489
                        return;
490
                
491
                if (isDynamicSearch()) // Puede que sobre este if
492
                {                        
493
                        // Get a sorted copy of all items
494
                        this.itemsSearchesShow = this.itemsShowed.toArray();
495
                        
496
                        // Do the search of the rank
497
                        BinaryRankOfItemsSeek search = new BinaryRankOfItemsSeek();
498
                        search.binaryRankSeek();
499
                                                
500
                        // To obtain the range of items to showing
501
                        lowIndex = search.getLowIndex();
502
                        hightIndex = search.getHightIndex();                         
503
                        
504
                        this.dynamicSearchDone = true;
505
                        
506
                        // Get the items
507
                        switch(this.getSearchBehavior())
508
                        {
509
                                case MAINTAIN_ORIGINAL_POSITION_DYNAMIC_SEARCH: // If maintain original position // REVISAR y HACER                                        
510
                                        int numberOfItems = hightIndex - lowIndex;
511
                                        
512
                                        this.getDynamicItemsSearch(search, lowIndex, hightIndex);
513
                                        
514
                                        if (numberOfItems > 0)
515
                                        {                                                
516
                                                int positions[] = new int[numberOfItems];
517
                                                
518
                                                int positionArrayIndex = 0;
519
                                                
520
                                                // Gets the items ordered
521
                                                this.getDynamicItemsSearch(search, lowIndex, hightIndex);
522
                                                
523
                                                // Gets the position of the items in the original position
524
                                                for (int i = lowIndex; i < hightIndex; i++)
525
                                                {
526
                                                        positions[positionArrayIndex] = super.getParentIndexOf(this.itemsSearchesShow[i]);
527
                                                        positionArrayIndex ++;
528
                                                }
529
                                                Arrays.sort(positions);
530
                                                
531
                                                this.itemsSearchesShow = new Object[numberOfItems]; // Remove the array
532
                
533
                                                // Get the items at the original position
534
                                                for (int i = 0; i < numberOfItems; i++)
535
                                                        this.itemsSearchesShow[i] = super.getParentElementAt(positions[i]);        
536
                                        }
537
                                        break;
538
                                case ORDERED_DYNAMIC_SEARCH: // If ordered                        
539
                                        
540
                                        this.getDynamicItemsSearch(search, lowIndex, hightIndex);
541
                                        
542
                                        break;
543
                                case DISORDERED_DYNAMIC_SEARCH: // If disordered //HACER                                
544

    
545
                                        this.getDynamicItemsSearch(search, lowIndex, hightIndex);
546
                                        this.disorderItemsCopy();
547
                        }                        
548
                }
549
        }
550

    
551
        /*
552
         *  (non-Javadoc)
553
         * @see org.gvsig.gui.beans.swing.jComboBoxItemsSeeker.AbstractDefaultComboBoxItemsSeekerConfigurableModel#setItemsCopyToArray()
554
         */
555
        protected void setItemsCopyToArray() {
556
                this.itemsSearchesShow = null;
557
                this.itemsSearchesShow = this.itemsShowed.toArray();
558
                this.itemsInTheArray = true;
559
                this.stateAllItems = STATE_ITEMS_ARE_ORDERED;
560
        }
561

    
562
        ////// END OTHER METHODS //////
563
}