Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.dynform / org.gvsig.tools.dynform.impl / src / main / java / org / gvsig / tools / dynform / impl / DefaultJDynForm.java @ 2031

History | View | Annotate | Download (23.8 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 modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.tools.dynform.impl;
24

    
25
import org.gvsig.tools.dynform.spi.dynform.AbstractJDynForm;
26
import java.util.ArrayList;
27
import java.util.HashMap;
28
import java.util.Iterator;
29
import java.util.List;
30
import java.util.Map;
31

    
32
import javax.swing.Action;
33
import javax.swing.JComponent;
34
import javax.swing.JTabbedPane;
35

    
36
import org.apache.commons.lang3.StringUtils;
37
import org.gvsig.tools.ToolsLocator;
38
import org.gvsig.tools.dataTypes.CoercionException;
39
import org.gvsig.tools.dataTypes.DataType;
40
import org.gvsig.tools.dataTypes.DataTypes;
41
import org.gvsig.tools.dynform.DynFormDefinition;
42
import org.gvsig.tools.dynform.DynFormFieldDefinition;
43
import org.gvsig.tools.dynform.JDynFormField;
44
import org.gvsig.tools.dynform.JDynFormField.JDynFormFieldListener;
45
import org.gvsig.tools.dynform.spi.dynformfield.SupportPopupMenu;
46
import org.gvsig.tools.dynobject.DynClass;
47
import org.gvsig.tools.dynobject.DynField;
48
import org.gvsig.tools.dynobject.DynField_v2;
49
import org.gvsig.tools.dynobject.DynObject;
50
import org.gvsig.tools.service.ServiceException;
51

    
52
import com.jgoodies.forms.builder.DefaultFormBuilder;
53
import com.jgoodies.forms.layout.CellConstraints;
54
import com.jgoodies.forms.layout.FormLayout;
55
import com.jgoodies.forms.layout.RowSpec;
56
import java.util.Collection;
57
import org.gvsig.tools.dynform.spi.DynFormSPIManager;
58
import org.gvsig.tools.dynform.spi.DynFormSPIManager.ComponentsFactory;
59
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.TAG_DYNFORM_SEPARATOR;
60
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_CLEAR;
61
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_ISMODIFIED;
62
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_ISREADONLY;
63
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_ONFIELDCHANGED;
64
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_ONFIELDENTER;
65
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_ONFIELDEXIT;
66
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_ONLOAD;
67
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_ONSETVALUES;
68
import static org.gvsig.tools.dynform.spi.DynFormSPIManager.USERCODE_FORM_VALIDATE;
69
import org.gvsig.tools.dynform.spi.dynform.JDynFormFactory;
70
import org.gvsig.tools.dynform.spi.dynformfield.JDynFormFieldFactory;
71
import org.gvsig.tools.dynform.spi.dynformfield.AbstractJDynFormField;
72
import org.gvsig.tools.dynobject.Tags;
73
import org.gvsig.tools.i18n.I18nManager;
74

    
75
@SuppressWarnings("UseSpecificCatch")
76
public class DefaultJDynForm extends AbstractJDynForm implements JDynFormFieldListener {
77

    
78
    private Map components = null;
79
    private final ComponentsFactory componentsFactory;
80

    
81
    public DefaultJDynForm(
82
            DynFormSPIManager manager, 
83
            JDynFormFactory factory,
84
            DynFormDefinition definition,
85
            DynFormContext context
86
        ) {
87
        super(manager, factory, definition, context);
88
        this.components = new HashMap();
89
        this.componentsFactory = manager.createDefaultComponentsFactory();
90
    }
91

    
92
    @Override
93
    protected JComponent getFieldsContainer() {
94

    
95
        try {
96
            JComponent component;
97
            switch (this.getLayoutMode()) {
98
                case USE_PLAIN:
99
                case USE_TREE:
100
                default:
101
                    component = getFieldsContainerPlain();
102
                    break;
103
                case USE_TABS:
104
                    component = getFieldsContainerUseTabs();
105
                    break;
106
                case USE_SEPARATORS:
107
                    component = getFieldsContainerUseSeparators();
108
                    break;
109
            }
110
            this.callUserEvent(USERCODE_FORM_ONLOAD, this);
111
            return component;
112
        } catch (ServiceException ex) {
113
            throw new RuntimeException(ex);
114
        }
115
    }
116

    
117
    private JComponent getFieldsContainerPlain() throws ServiceException {
118
        FormLayout layout = new FormLayout(
119
                "left:pref,  8px,  fill:80dlu:grow", "pref");
120

    
121
        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
122
        builder.defaultRowSpec(new RowSpec(
123
                RowSpec.TOP,
124
                builder.getLayout().getRowSpec(1).getSize(),
125
                builder.getLayout().getRowSpec(1).getResizeWeight()));
126

    
127
        List fields = this.getDefinition().getDefinitions();
128
        Iterator it = fields.iterator();
129
        while (it.hasNext()) {
130
            DynFormFieldDefinition fieldDefinition = (DynFormFieldDefinition) it.next();
131
            if (fieldDefinition.isHidden()) {
132
                continue;
133
            }
134
            JDynFormFieldFactory factory = getServiceManager().getJDynFormFieldFactory(
135
                    this.getContext(),
136
                    fieldDefinition
137
            );
138
            JDynFormField jfield = factory.create(
139
                    getServiceManager(), 
140
                    this.componentsFactory,
141
                    fieldDefinition, 
142
                    null
143
            );
144
            if (jfield instanceof AbstractJDynFormField) {
145
                ((AbstractJDynFormField) jfield).setForm(this);
146
            }
147
            if (this.isReadOnly()) {
148
                jfield.setReadOnly(true);
149
            } else {
150
                jfield.setReadOnly(fieldDefinition.isReadOnly());
151
            }
152
            jfield.addListener(this);
153
            double resizeWeight = jfield.getResizeWeight();
154
            if( resizeWeight>0 ) {
155
                builder.appendRow(new RowSpec(
156
                    RowSpec.FILL,
157
                    builder.getLayout().getRowSpec(1).getSize(),
158
                    resizeWeight)
159
                );
160
                builder.append(jfield.getJLabel());
161
                builder.add(
162
                        jfield.asJComponent(), 
163
                        new CellConstraints(
164
                            builder.getColumn(), 
165
                            builder.getRow(),
166
                            CellConstraints.FILL,
167
                            CellConstraints.FILL
168
                        )
169
                );
170
                builder.nextColumn();
171
            } else {
172
                builder.append(jfield.getJLabel(), jfield.asJComponent());
173
            }
174
            this.components.put(jfield.getName(), jfield);
175
        }
176
        return builder.getPanel();
177
    }
178

    
179
    private JComponent getFieldsContainerUseSeparators() throws ServiceException {
180
        List<String> groups = this.getDefinition().getGroups();
181

    
182
        FormLayout layout = new FormLayout(
183
                "left:pref,  8px,  fill:80dlu:grow", "pref");
184

    
185
        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
186
        builder.defaultRowSpec(new RowSpec(
187
                RowSpec.TOP,
188
                builder.getLayout().getRowSpec(1).getSize(),
189
                builder.getLayout().getRowSpec(1).getResizeWeight()));
190

    
191
        for (String group : groups) {
192
            boolean firstfield = true;
193
            List fields = this.getDefinition().getDefinitions(group);
194
            Iterator it = fields.iterator();
195
            while (it.hasNext()) {
196
                DynFormFieldDefinition fieldDefinition = (DynFormFieldDefinition) it.next();
197
                if (fieldDefinition.isHidden()) {
198
                    continue;
199
                }
200
                JDynFormFieldFactory factory = getServiceManager().getJDynFormFieldFactory(
201
                        this.getContext(),
202
                        fieldDefinition
203
                );
204
                JDynFormField jfield = factory.create(
205
                        getServiceManager(), 
206
                        this.componentsFactory,
207
                        fieldDefinition, 
208
                        null
209
                );
210
                if (jfield instanceof AbstractJDynFormField) {
211
                    ((AbstractJDynFormField) jfield).setForm(this);
212
                }
213
                jfield.addListener(this);
214
                if (this.isReadOnly()) {
215
                    jfield.setReadOnly(this.isReadOnly());
216
                }
217

    
218
                List<Action> customActions = getCustomFields(fieldDefinition.getDataType());
219

    
220
                if (customActions != null && !customActions.isEmpty()) {
221
                    Iterator it2 = customActions.iterator();
222
                    while (it2.hasNext()) {
223
                        Object obj = it2.next();
224
                        if (obj != null) {
225
                            Action act = (Action) obj;
226
                            jfield.addActionToPopupMenu((String) act.getValue(Action.NAME), act);
227
                        } else {
228
                            jfield.addSeparatorToPopupMenu();
229
                        }
230
                    }
231
                }
232
                if( firstfield ) {
233
                    firstfield = false;
234
                    builder.appendSeparator(group);
235
                }
236
                double resizeWeight = jfield.getResizeWeight();
237
                if( resizeWeight>0 ) {
238
                    builder.appendRow(new RowSpec(
239
                        RowSpec.FILL,
240
                        builder.getLayout().getRowSpec(1).getSize(),
241
                        resizeWeight)
242
                    );
243
                    builder.append(jfield.getJLabel());
244
                    builder.add(
245
                            jfield.asJComponent(), 
246
                            new CellConstraints(
247
                                builder.getColumn(), 
248
                                builder.getRow(),
249
                                CellConstraints.FILL,
250
                                CellConstraints.FILL
251
                            )
252
                    );
253
                    builder.nextColumn();
254
                } else {
255
                    builder.append(jfield.getJLabel(), jfield.asJComponent());
256
                }
257
                this.components.put(jfield.getName(), jfield);
258
            }
259
        }
260
        return builder.getPanel();
261
    }
262

    
263
    private JComponent getFieldsContainerUseTabs() throws ServiceException {
264

    
265
        JTabbedPane tabbedPane = new JTabbedPane();
266
        tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
267
        if (this.getDefinition().getTags().has("TabPlacement")) {
268
            try {
269
                tabbedPane.setTabPlacement(this.getDefinition().getTags().getInt("TabPlacement"));
270
            } catch (Exception e) {
271
                // Ignorada
272
            }
273
        }
274
        I18nManager i18n = ToolsLocator.getI18nManager();
275
        List<String> groups = this.getDefinition().getGroups();
276
        for (String group : groups) {
277
            FormLayout layout = new FormLayout(
278
                    "left:pref,  8px,  fill:80dlu:grow", "pref");
279
            DefaultFormBuilder builder = new DefaultFormBuilder(layout);
280
            builder.defaultRowSpec(new RowSpec(
281
                    RowSpec.TOP,
282
                    builder.getLayout().getRowSpec(1).getSize(),
283
                    builder.getLayout().getRowSpec(1).getResizeWeight()));
284
            List fields = this.getDefinition().getDefinitions(group);
285
            boolean hasFields = false;
286
            Iterator it = fields.iterator();
287
            while (it.hasNext()) {
288
                DynFormFieldDefinition fieldDefinition = (DynFormFieldDefinition) it.next();
289
                if (fieldDefinition.isHidden()) {
290
                    continue;
291
                }
292
                JDynFormFieldFactory factory = getServiceManager().getJDynFormFieldFactory(
293
                        this.getContext(),
294
                        fieldDefinition
295
                );
296
                JDynFormField jfield = factory.create(
297
                        getServiceManager(), 
298
                        this.componentsFactory,
299
                        fieldDefinition, 
300
                        null
301
                );
302
                if (jfield instanceof AbstractJDynFormField) {
303
                    ((AbstractJDynFormField) jfield).setForm(this);
304
                }
305
                jfield.setReadOnly(this.isReadOnly());
306
                jfield.addListener(this);
307
                if (this.isReadOnly()) {
308
                    jfield.setReadOnly(this.isReadOnly());
309
                }
310
                hasFields = true;
311
                Tags tags = jfield.getDefinition().getTags();
312
                if( tags!=null ) {
313
                    String sep = tags.getString(TAG_DYNFORM_SEPARATOR, null);
314
                    if( !StringUtils.isBlank(sep) ) {
315
                        builder.appendSeparator(i18n.getTranslation(sep));
316
                    }
317
                }                
318
                double resizeWeight = jfield.getResizeWeight();
319
                if( resizeWeight>0 ) {
320
                    builder.appendRow(new RowSpec(
321
                        RowSpec.FILL,
322
                        builder.getLayout().getRowSpec(1).getSize(),
323
                        resizeWeight)
324
                    );
325
                    builder.append(jfield.getJLabel());
326
                    builder.add(
327
                            jfield.asJComponent(), 
328
                            new CellConstraints(
329
                                builder.getColumn(), 
330
                                builder.getRow(),
331
                                CellConstraints.FILL,
332
                                CellConstraints.FILL
333
                            )
334
                    );
335
                    builder.nextColumn();
336
                } else {
337
                    builder.append(jfield.getJLabel(), jfield.asJComponent());
338
                }
339

    
340
                this.components.put(jfield.getName(), jfield);
341
            }
342
            if( hasFields ) {
343
                String tablabel = group;
344
                if (StringUtils.isEmpty(tablabel)) {
345
                    tablabel = ToolsLocator.getI18nManager().getTranslation("General");
346
                }
347
                tablabel = i18n.getTranslation(tablabel);
348
                tabbedPane.addTab(tablabel, builder.getPanel());
349
            }
350
        }
351

    
352
        try {
353
            String defaultGroupName = (String) this.getDefinition().getTags().get("defaultGroup", DataTypes.STRING);
354
            List<String> groupsNames = this.getDefinition().getGroups();
355
            int groupIndex = groupsNames.indexOf(defaultGroupName);
356
            if (groupIndex >= 0) {
357
                tabbedPane.setSelectedIndex(groupIndex);
358
            }
359
        } catch (Exception ex) {
360
            // Ignore errors and don't set a tab by default
361
        }
362

    
363
        return tabbedPane;
364
    }
365

    
366
    @Override
367
    public void setReadOnly(boolean readOnly) {
368
        if( this.isReadOnly() == readOnly ) {
369
            return;
370
        }
371
        super.setReadOnly(readOnly);
372
        if (this.isContentsInitialized()) {
373
            Iterator it = this.getFieldsIterator();
374
            while (it.hasNext()) {
375
                JDynFormField field = (JDynFormField) it.next();
376
                if( readOnly ) {
377
                    field.setReadOnly(true);
378
                } else if( field.getDefinition().isReadOnly() ) {
379
                    field.setReadOnly(true);
380
                } else {
381
                    field.setReadOnly(false);
382
                }
383
            }
384
        }
385
    }
386

    
387
    @Override
388
    public void setValues(DynObject values) {
389
        /*
390
         * TODO: Probablemente fuese mas acertado recorrer los controles de
391
         * components y a partir de ellos acceder a los valores del DynObject
392
         * recibido. Eso permitiria trabajar mejor con herencia de DynObject.
393
         * Habria que hacer lo mismo con el getValues.
394
         */
395
        if (!this.isContentsInitialized()) {
396
            this.values = values;
397
            return;
398
        }
399
        DynClass def = values.getDynClass();
400
        DynField[] fields = def.getDynFields();
401
        for (int i = 0; i < fields.length; i++) {
402
            DynField field = fields[i];
403
            if( field.isHidden() ) {
404
                continue;
405
            }
406
            String name = field.getName();
407
            if (name == null || name.isEmpty()) {
408
                LOGGER.warn("Field name " + i + " of '" + def.getFullName() + "' is null or empty ");
409
                continue;
410
            }
411
            JDynFormField jfield = (JDynFormField) this.getField(name);
412
            if (jfield == null) {
413
                LOGGER.warn("Can't retrieve form field asociated to the field '" + name + "' of class '" + def.getFullName() + "'.");
414
                continue;
415
            }
416
            if (values.getDynValue(name) == null) {
417
                if (fields[i].getDataType().getType() == DataTypes.LIST) {
418
                    try {
419
                        if (((DynField_v2) fields[i]).getDynClassOfItems() != null) {
420
                            values.setDynValue(name, new ArrayList<>());
421
                        }
422
                    } catch (Exception e) {
423
                        LOGGER.warn("Problems initializing the DynObject List", e);
424
                    }
425
                }
426
            }
427
            jfield.setValue(values.getDynValue(name));
428
        }
429
        this.callUserEvent(USERCODE_FORM_ONSETVALUES, this, values);
430
        try {
431
            if( (boolean) this.callUserFunction(USERCODE_FORM_ISREADONLY, this) ) {
432
                this.setReadOnly(true);
433
            }
434
        } catch (Exception ex) {
435
        }
436
    }
437

    
438
    @Override
439
    public void getValues(DynObject values) {
440
        if (values == null) {
441
            return;
442
        }
443
        DynField[] fields = values.getDynClass().getDynFields();
444
        for (DynField field : fields) {
445
            String name = field.getName();
446
            JDynFormField jfield = (JDynFormField) this.getField(name);
447
            if (jfield != null && !jfield.isReadOnly()) {
448
                try {
449
                    jfield.fetch(values);
450
                } catch (Exception ex) {
451
                    LOGGER.warn("Can't get value of field '" + name + "'.", ex);
452
                }
453
            }
454
        }
455
    }
456

    
457
    @Override
458
    public boolean hasValidValues() {
459
        Iterator it = this.getFieldsIterator();
460
        while (it.hasNext()) {
461
            JDynFormField jfield = (JDynFormField) it.next();
462
            if (!jfield.hasValidValue()) {
463
                return false;
464
            }
465
        }
466
        try {
467
            return (boolean) this.callUserFunction(USERCODE_FORM_VALIDATE, this);
468
        } catch (Exception ex) {
469
        }
470
        return true;
471
    }
472

    
473
    @Override
474
    public boolean hasValidValues(List<String> fieldsName) {
475
        if (fieldsName == null) {
476
            fieldsName = new ArrayList<>();
477
        }
478
        Iterator it = this.getFieldsIterator();
479
        while (it.hasNext()) {
480
            JDynFormField jfield = (JDynFormField) it.next();
481
            if (!jfield.hasValidValue()) {
482
                fieldsName.add(jfield.getName());
483
            }
484
        }
485
        return fieldsName.isEmpty();
486
    }
487

    
488
    @Override
489
    public Object getValue(String fieldName) {
490
        JDynFormField field = (JDynFormField) this.getField(fieldName);
491
        return field.getValue();
492
    }
493

    
494
    @Override
495
    public void setValue(String fieldName, Object value) {
496
        JDynFormField field = (JDynFormField) this.getField(fieldName);
497
        try {
498
            value = field.getDefinition().getDataType().coerce(value);
499
        } catch (CoercionException e) {
500
            String msg = "Invalid value '" + ((value == null) ? "(null)" : value.toString()) + "' for field '" + fieldName + "'.";
501
            LOGGER.warn(msg, e);
502
            throw new RuntimeException(msg, e);
503
        }
504
        field.setValue(value);
505
    }
506

    
507
    @Override
508
    public boolean isModified() {
509
        if( this.isReadOnly() ) {
510
            return false;
511
        }
512
        try {
513
            return (boolean) this.callUserFunction(USERCODE_FORM_ISMODIFIED, this, values);
514
        } catch (NoSuchMethodException ex) {
515
        } catch (Exception ex) {
516
            LOGGER.warn("Error calling user function form_IsModified.",ex);
517
        }
518
        Iterator it = this.getFieldsIterator();
519
        while (it.hasNext()) {
520
            JDynFormField jfield = (JDynFormField) it.next();
521
            if (jfield.isModified()) {
522
                return true;
523
            }
524
        }
525
        return false;
526
    }
527

    
528
    @Override
529
    public void fieldEnter(JDynFormField field) {
530
        message(field.getDefinition().getDescription());
531
        this.callUserEvent(USERCODE_FORM_ONFIELDENTER, this, field);
532
    }
533

    
534
    @Override
535
    public void fieldExit(JDynFormField field) {
536
        message();
537
        this.callUserEvent(USERCODE_FORM_ONFIELDEXIT, this, field);
538
    }
539

    
540
    @Override
541
    public void message(JDynFormField field, String message) {
542
        message(message);
543
    }
544

    
545
    @Override
546
    public void fieldChanged(JDynFormField field) {
547
        fireFieldChangeEvent(field);
548
        this.callUserEvent(USERCODE_FORM_ONFIELDCHANGED, this, field);
549
    }
550

    
551
    @Override
552
    public JDynFormField getField(String fieldName) {
553
        JDynFormField field = (JDynFormField) this.components.get(fieldName);
554
        return field;
555
    }
556

    
557
    public Iterator getFieldsIterator() {
558
        if (!this.isContentsInitialized()) {
559
            this.initComponents();
560
        }
561
        return this.components.values().iterator();
562
    }
563

    
564
    public Collection getShowFields() {
565
        return this.components.values();
566
    }
567

    
568
    @Override
569
    public void clear() {
570
        Iterator it = this.components.entrySet().iterator();
571
        while (it.hasNext()) {
572
            Map.Entry entry = (Map.Entry) it.next();
573
            ((JDynFormField) (entry.getValue())).clear();
574
        }
575
        this.callUserEvent(USERCODE_FORM_CLEAR, this);
576
    }
577

    
578
    @Override
579
    public void addActionToPopupMenu(DataType tipo, String name, Action action) {
580
        super.addActionToPopupMenu(tipo, name, action);
581
        if ( this.isContentsInitialized() ) {
582
            Iterator it = this.components.keySet().iterator();
583
            while (it.hasNext()) {
584
                String key = (String) it.next();
585
                Object obj = this.components.get(key);
586
                if (obj instanceof JDynFormField) {
587
                    JDynFormField field = (JDynFormField) obj;
588
                    if (tipo == field.getDefinition().getDataType()) {
589
                        if (field.asJComponent() instanceof SupportPopupMenu) {
590
                            field.addActionToPopupMenu(name, action);
591
                        }
592
                    }
593
                }
594
            }
595
        }
596
    }
597

    
598
    @Override
599
    public void addSeparatorToPopupMenu(DataType tipo) {
600
        super.addSeparatorToPopupMenu(tipo);
601
        if ( this.isContentsInitialized() ) {
602
            Iterator it = this.components.keySet().iterator();
603
            while (it.hasNext()) {
604
                String key = (String) it.next();
605
                Object obj = this.components.get(key);
606
                if (obj instanceof JDynFormField) {
607
                    JDynFormField field = (JDynFormField) obj;
608
                    if (tipo == field.getDefinition().getDataType()) {
609
                        if (field.asJComponent() instanceof SupportPopupMenu) {
610
                            ((SupportPopupMenu) field.asJComponent()).addSeparatorToPopupMenu();
611
                        }
612
                    }
613
                }
614
            }
615
        }
616
    }
617

    
618
    @Override
619
    public void setBorder(boolean border) {
620
        super.setBorder(border && this.getShowFields().size() >1);
621
    }
622

    
623
}