1   /*
2    * Copyright 2003 - 2013 The eFaps Team
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Revision:        $Rev$
17   * Last Changed:    $Date$
18   * Last Changed By: $Author$
19   */
20  
21  package org.efaps.admin.ui.field;
22  
23  import java.util.HashMap;
24  import java.util.Map;
25  import java.util.UUID;
26  
27  import org.efaps.admin.common.MsgPhrase;
28  import org.efaps.admin.datamodel.ui.IUIProvider;
29  import org.efaps.admin.datamodel.ui.UIInterface;
30  import org.efaps.admin.ui.AbstractCollection;
31  import org.efaps.admin.ui.AbstractCommand.Target;
32  import org.efaps.admin.ui.AbstractUserInterfaceObject;
33  import org.efaps.admin.ui.Form;
34  import org.efaps.admin.ui.Table;
35  import org.efaps.ci.CIAdminUserInterface;
36  import org.efaps.db.MultiPrintQuery;
37  import org.efaps.db.QueryBuilder;
38  import org.efaps.util.EFapsException;
39  import org.efaps.util.RequestHandler;
40  import org.efaps.util.cache.CacheLogListener;
41  import org.efaps.util.cache.CacheReloadException;
42  import org.efaps.util.cache.InfinispanCache;
43  import org.infinispan.Cache;
44  import org.slf4j.Logger;
45  import org.slf4j.LoggerFactory;
46  
47  /**
48   * This class represents the Fields of the UserInterface.
49   *
50   * @author The eFaps Team
51   * @version $Id$
52   */
53  public class Field
54      extends AbstractUserInterfaceObject
55  {
56      /**
57       * Used to define the different display modes for the Userinterface.
58       */
59      public static enum Display {
60          /** the displayed Field is editabel. */
61          EDITABLE,
62          /** the displayed Field is read only.. */
63          READONLY,
64          /** the displayed Field is rendered but hidden. */
65          HIDDEN,
66          /** the field will not be displayed. */
67          NONE;
68      }
69  
70      /**
71       * Needed for serialization.
72       */
73      private static final long serialVersionUID = 1L;
74  
75      /**
76       * Name of the Cache by ID.
77       */
78      private static String IDCACHE = Field.class.getName();
79  
80      /**
81       * Logger for this class.
82       */
83      private static final Logger LOG = LoggerFactory.getLogger(Field.class);
84  
85      /**
86       * This is the value in the create process. Default value is <i>null</i>.
87       *
88       * @see #setCreateValue
89       * @see #getCreateValue
90       */
91      private String createValue = null;
92  
93      /**
94       * Instance variable to hold the label.
95       *
96       * @see #setLabel
97       * @see #getLabel
98       */
99      private String label = null;
100 
101     /**
102      * The filter for this field.
103      */
104     private final Filter filter = new Filter();
105 
106     /**
107      * Is a field multi line? If yes, the value must be higher than the default
108      * value <i>1</i>. The value is only used for a create or a modify form.
109      *
110      * @see #setRows
111      * @see #getRows
112      */
113     private int rows = 1;
114 
115     /**
116      * Number of columns for a field. It is used only for a create or a modify
117      * form. Default value is <i>20</i>. The column size is not the size of a
118      * field in the database!
119      *
120      * @see #setCols
121      * @see #getCols
122      */
123     private int cols = 20;
124 
125     /**
126      * Is a field required? Default value is <i>false</i>.
127      *
128      * @see #setRequired
129      * @see #isRequired
130      */
131     private boolean required = false;
132 
133     /**
134      * Instance variable to hold the reference to call.
135      *
136      * @see #setReference
137      * @see #getReference
138      */
139     private String reference = null;
140 
141     /**
142      * Instance variable to hold the selected index.
143      *
144      * @see #setSelIndex
145      * @see #getSelIndex
146      */
147     private int selIndex;
148 
149     /**
150      * The field has an icon..
151      *
152      * @see #setIcon
153      * @see #getIcon
154      */
155     private String icon = null;
156 
157     /**
158      * The target of the field href is the content frame.
159      *
160      * @set #getTarget
161      * @see #setTarget
162      */
163     private Target target = Target.UNKNOWN;
164 
165     /**
166      * The type icon for this field is shown if value is set to true.
167      *
168      * @see #setShowTypeIcon
169      * @see #isShowTypeIcon
170      */
171     private boolean showTypeIcon = false;
172 
173     /**
174      * The numbering for the field is activated/deactivated.
175      */
176     private boolean showNumbering = false;
177 
178     /**
179      * The class is used to generate for a field user specific field values.
180      *
181      * @see #setClassUI
182      * @see #getClassUI
183      */
184     private UIInterface classUI = null;
185 
186     /**
187      * The class is used to generate for a field user specific field values.
188      */
189     private IUIProvider uiProvider = null;
190 
191     /**
192      * This field can be sorted in a Webtable.
193      *
194      * @see #isSortAble()
195      */
196     private boolean sortAble = true;
197 
198     /**
199      * The width of the field as weighted int.
200      */
201     private int width;
202 
203     /**
204      * Is the width of this field fixed or or weighted.
205      */
206     private boolean fixedWidth = false;
207 
208     /**
209      * Should the Label been hidden.
210      */
211     private boolean hideLabel = false;
212 
213     /**
214      * Should rows been spanned.
215      */
216     private int rowSpan = 0;
217 
218     /**
219      * Map stores the target mode to display relations for this field.
220      */
221     private final Map<AbstractUserInterfaceObject.TargetMode, Field.Display> mode2display =
222         new HashMap<AbstractUserInterfaceObject.TargetMode, Field.Display>();
223 
224     /**
225      * Stores the select that returns the value for this field.
226      */
227     private String select;
228 
229     /**
230      * Stores the name of the attribute that returns the value for this field.
231      */
232     private String attribute;
233 
234     /**
235      * Stores the phrase that returns the value for this field.
236      */
237     private String phrase;
238 
239     /**
240      * Stores the select that returns the value for the alternate OID.
241      */
242     private String selectAlternateOID;
243 
244     /**
245      * Stores the value of the align attribute for a field.
246      */
247     private String align = "left";
248 
249     /**
250      * UUID of the parent collection. It is used to have a lazy low cost
251      * access to the collection this FIeld belongs to.
252      */
253     private UUID collectionUUID;
254 
255     /**
256      * Stores the classification for this field.
257      */
258     private String classificationName;
259 
260     /**
261      * MessagePhrase String.
262      */
263     private String msgPhrase;
264 
265     /**
266      * This is the constructor of the field class.
267      *
268      * @param _id id of the field instance
269      * @param _uuid UUID of the field instance
270      * @param _name name of the field instance
271      */
272     public Field(final long _id,
273                  final String _uuid,
274                  final String _name)
275     {
276         super(_id, _uuid, _name);
277 
278     }
279 
280     /**
281      * Test, if the value of instance variable
282      * {@link org.efaps.admin.ui.AbstractCommand.target} is
283      * equal to {@link org.efaps.admin.ui.AbstractCommand.TARGET_CONTENT}.
284      *
285      * @return <i>true</i> if value is equal, otherwise false
286      * @see #target
287      * @see #getTarget
288      */
289     public boolean isTargetContent()
290     {
291         return getTarget() == Target.CONTENT;
292     }
293 
294     /**
295      * Test, if the value of instance variable
296      * {@link org.efaps.admin.ui.AbstractCommand.target} is
297      * equal to {@link org.efaps.admin.ui.AbstractCommand.TARGET_POPUP}.
298      *
299      * @return <i>true</i> if value is equal, otherwise false
300      * @see #target
301      * @see #getTarget
302      */
303     public boolean isTargetPopup()
304     {
305         return getTarget() == Target.POPUP;
306     }
307 
308     /**
309      * Test, if the value of instance variable
310      * {@link org.efaps.admin.ui.AbstractCommand.target} is
311      * equal to {@link org.efaps.admin.ui.AbstractCommand.TARGET_HIDDEN}.
312      *
313      * @return <i>true</i> if value is equal, otherwise false
314      * @see #target
315      * @see #getTarget
316      */
317     public boolean isTargetHidden()
318     {
319         return getTarget() == Target.HIDDEN;
320     }
321 
322     /**
323      * Getter method for the instance variable {@link #align}.
324      *
325      * @return value of instance variable {@link #align}
326      */
327     public String getAlign()
328     {
329         return this.align;
330     }
331 
332     /**
333      * This is the getter method for instance variable {@link #createValue}.
334      *
335      * @return the value of the instance variable {@link #createValue}.
336      * @see #createValue
337      * @see #setCreateValue
338      */
339     public String getCreateValue()
340     {
341         return this.createValue;
342     }
343 
344     /**
345      * This is the getter method for instance variable {@link #label}.
346      *
347      * @return the value of the instance variable {@link #label}.
348      * @see #label
349      * @see #setLabel
350      */
351     public String getLabel()
352     {
353         return this.label;
354     }
355 
356     /**
357      * This is the getter method for instance variable {@link #rows}.
358      *
359      * @return the value of the instance variable {@link #rows}.
360      * @see #rows
361      * @see #setRows
362      */
363     public int getRows()
364     {
365         return this.rows;
366     }
367 
368     /**
369      * This is the getter method for instance variable {@link #cols}.
370      *
371      * @return the value of the instance variable {@link #cols}.
372      * @see #cols
373      * @see #setCols
374      */
375     public int getCols()
376     {
377         return this.cols;
378     }
379 
380     /**
381      * This is the getter method for instance variable {@link #required}.
382      *
383      * @return the value of the instance variable {@link #required}.
384      * @see #required
385      * @see #setRequired
386      */
387     public boolean isRequired()
388     {
389         return this.required;
390     }
391 
392     /**
393      * This is the getter method for instance variable {@link #hideLabel}.
394      *
395      * @return the value of the instance variable {@link #hideLabel}.
396      */
397     public boolean isHideLabel()
398     {
399         return this.hideLabel;
400     }
401 
402     /**
403      * This is the getter method for instance variable {@link #rowSpan}.
404      *
405      * @return the value of the instance variable {@link #rowSpan}.
406      */
407     public int getRowSpan()
408     {
409         return this.rowSpan;
410     }
411 
412     /**
413      * This is the getter method for instance variable {@link #reference}.
414      *
415      * @return the value of the instance variable {@link #reference}.
416      * @see #reference
417      * @see #setReference
418      */
419     public String getReference()
420     {
421         return this.reference;
422     }
423 
424     /**
425      * This is the getter method for instance variable {@link #selIndex}.
426      *
427      * @return the value of the instance variable {@link #selIndex}.
428      * @see #selIndex
429      * @see #setSelIndex
430      */
431     public int getSelIndex()
432     {
433         return this.selIndex;
434     }
435 
436     /**
437      * This is the setter method for instance variable {@link #sortAble}.
438      *
439      * @return the value of the instance variable {@link #sortAble}.
440      * @see #sortAble
441      * @see #setSortAble
442      */
443     public boolean isSortAble()
444     {
445         return this.sortAble;
446     }
447 
448     /**
449      * This is the getter method for instance variable {@link #icon}.
450      *
451      * @return the value of the instance variable {@link #icon}.
452      * @see #icon
453      * @see #setIcon
454      */
455     public String getIcon()
456     {
457         return this.icon;
458     }
459 
460     /**
461      * This is the setter method for the instance variable {@link #target}.
462      *
463      * @return value of instance variable {@link #target}
464      * @see #target
465      * @see #setTarget
466      */
467     public Target getTarget()
468     {
469         return this.target;
470     }
471 
472     /**
473      * This is the setter method for the instance variable {@link #showTypeIcon}
474      * .
475      *
476      * @return value of instance variable {@link #showTypeIcon}
477      * @see #showTypeIcon
478      * @see #setShowTypeIcon
479      */
480     public boolean isShowTypeIcon()
481     {
482         return this.showTypeIcon;
483     }
484 
485     /**
486      * This is the getter method for the instance variable {@link #showNumbering}.
487      *
488      * @return value of instance variable {@link #showNumbering}
489      */
490     public boolean isShowNumbering()
491     {
492         return this.showNumbering;
493     }
494 
495     /**
496      * This is the setter method for the instance variable {@link #classUI}.
497      *
498      * @return value of instance variable {@link #classUI}
499      * @see #classUI
500      * @see #setClassUI
501      */
502     public UIInterface getClassUI()
503     {
504         return this.classUI;
505     }
506 
507     /**
508      * This is the getter method for instance variable {@link #classUI}.
509      *
510      * @return value of instance variable {@link #classUI}
511      */
512     public IUIProvider getUIProvider()
513     {
514         return this.uiProvider == null ? (IUIProvider) this.classUI : this.uiProvider;
515     }
516 
517     /**
518      * This is the getter method for the instance variable {@link #width}.
519      *
520      * @return value of instance variable {@link #width}
521      */
522     public int getWidth()
523     {
524         if (this.width == 0) {
525             this.width = 1;
526         }
527         return this.width;
528     }
529 
530     /**
531      * This is the setter method for the instance variable {@link #width}.
532      *
533      * @param _value the width to set
534      */
535     private void setWidth(final String _value)
536     {
537         String strwidth = _value;
538         if (strwidth.endsWith("px")) {
539             this.fixedWidth = true;
540             strwidth = _value.substring(0, strwidth.length() - 2);
541         }
542         this.width = Integer.parseInt(strwidth);
543     }
544 
545     /**
546      * This is the getter method for the instance variable {@link #fixedWidth}.
547      *
548      * @return value of instance variable {@link #fixedWidth}
549      */
550     public boolean isFixedWidth()
551     {
552         return this.fixedWidth;
553     }
554 
555     /**
556      * Getter method for instance variable {@link #select}.
557      *
558      * @return value of instance variable {@link #select}
559      */
560     public String getSelect()
561     {
562         return this.select;
563     }
564 
565     /**
566      * Getter method for instance variable {@link #attribute}.
567      *
568      * @return value of instance variable {@link #attribute}
569      */
570     public String getAttribute()
571     {
572         return this.attribute;
573     }
574 
575     /**
576      * Getter method for instance variable {@link #phrase}.
577      *
578      * @return value of instance variable {@link #phrase}
579      */
580     public String getPhrase()
581     {
582         return this.phrase;
583     }
584 
585     /**
586      * @return the messagephrase for this field
587      * @throws EFapsException on error
588      */
589     public MsgPhrase getMsgPhrase()
590         throws EFapsException
591     {
592         MsgPhrase ret;
593         if (this.msgPhrase == null) {
594             ret = null;
595         } else if (this.msgPhrase
596                         .matches("[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}")) {
597             ret = MsgPhrase.get(UUID.fromString(this.msgPhrase));
598         } else {
599             ret = MsgPhrase.get(this.msgPhrase);
600         }
601         return ret;
602     }
603 
604     /**
605      * Getter method for the instance variable {@link #filter}.
606      *
607      * @return value of instance variable {@link #filter}
608      */
609     public Filter getFilter()
610     {
611         return this.filter;
612     }
613 
614     /**
615      * Getter method for the instance variable {@link #collectionOID}.
616      *
617      * @return value of instance variable {@link #collectionOID}
618      * @throws CacheReloadException on error
619      */
620     public AbstractCollection getCollection()
621         throws CacheReloadException
622     {
623         AbstractCollection ret = Form.get(this.collectionUUID);
624         if (ret == null) {
625             ret = Table.get(this.collectionUUID);
626         }
627         return ret;
628     }
629 
630     /**
631      * Setter method for instance variable {@link #collectionOID}.
632      *
633      * @param _collectionOID value for instance variable {@link #collectionOID}
634      */
635 
636     public void setCollectionUUID(final UUID _collectionOID)
637     {
638         this.collectionUUID = _collectionOID;
639     }
640 
641 
642     /**
643      * Getter method for instance variable {@link #selectAlternateOID}.
644      *
645      * @return value of instance variable {@link #selectAlternateOID}
646      */
647     public String getSelectAlternateOID()
648     {
649         return this.selectAlternateOID;
650     }
651 
652     /**
653      * Is this field editable in the given target mode. If not explicitly set in
654      * the definition following defaults apply:
655      * <ul>
656      * <li>ModeConnect: false</li>
657      * <li>ModeCreate: false</li>
658      * <li>ModeView: false</li>
659      * <li>ModePrint: false</li>
660      * <li>ModeEdit: false</li>
661      * <li>ModeSearch: false</li>
662      * </ul>
663      *
664      * @param _mode target mode
665      * @return true if editable in the given mode, else false
666      */
667     public boolean isEditableDisplay(final TargetMode _mode)
668     {
669         boolean ret = false;
670         if (this.mode2display.containsKey(_mode)) {
671             ret = this.mode2display.get(_mode).equals(Field.Display.EDITABLE);
672         }
673         return ret;
674     }
675 
676     /**
677      * Is this field read only in the given target mode. If not explicitly set
678      * in the definition following defaults apply:
679      * <ul>
680      * <li>ModeConnect: true</li>
681      * <li>ModeCreate: false</li>
682      * <li>ModeView: true</li>
683      * <li>ModePrint: true</li>
684      * <li>ModeEdit: true</li>
685      * <li>ModeSearch: false</li>
686      * </ul>
687      *
688      * @param _mode target mode
689      * @return true if editable in the given mode, else false
690      */
691     public boolean isReadonlyDisplay(final TargetMode _mode)
692     {
693         boolean ret = false;
694         if (this.mode2display.containsKey(_mode)) {
695             ret = this.mode2display.get(_mode).equals(Field.Display.READONLY);
696         } else if (_mode.equals(TargetMode.CONNECT) || _mode.equals(TargetMode.VIEW)
697                         || _mode.equals(TargetMode.EDIT) || _mode.equals(TargetMode.PRINT)) {
698             ret = true;
699         }
700         return ret;
701     }
702 
703     /**
704      * Is this field hidden in the given target mode. If not explicitly set in
705      * the definition following defaults apply:
706      * <ul>
707      * <li>ModeConnect: false</li>
708      * <li>ModeCreate: false</li>
709      * <li>ModeView: false</li>
710      * <li>ModeEdit: false</li>
711      * <li>ModeSearch: false</li>
712      * <li>ModePrint: false</li>
713      * </ul>
714      *
715      * @param _mode target mode
716      * @return true if editable in the given mode, else false
717      */
718     public boolean isHiddenDisplay(final TargetMode _mode)
719     {
720         boolean ret = false;
721         if (this.mode2display.containsKey(_mode)) {
722             ret = this.mode2display.get(_mode).equals(Field.Display.HIDDEN);
723         }
724         return ret;
725     }
726 
727     /**
728      * Is this field not displayed in the given target mode. If not explicitly
729      * set in the definition following defaults apply:
730      * <ul>
731      * <li>ModeConnect: false</li>
732      * <li>ModeCreate: true</li>
733      * <li>ModeView: false</li>
734      * <li>ModeEdit: false</li>
735      * <li>ModeSearch: true</li>
736      * <li>ModePrint: false</li>
737      * </ul>
738      *
739      * @param _mode target mode
740      * @return true if editable in the given mode, else false
741      */
742     public boolean isNoneDisplay(final TargetMode _mode)
743     {
744         boolean ret = false;
745         if (this.mode2display.containsKey(_mode)) {
746             ret = this.mode2display.get(_mode).equals(Field.Display.NONE);
747         } else if (_mode.equals(TargetMode.CREATE) || _mode.equals(TargetMode.SEARCH)) {
748             ret = true;
749         }
750         return ret;
751     }
752 
753     /**
754      * Method to get the display for the given target mode. The following
755      * defaults apply:
756      * <ul>
757      * <li>ModeConnect: READONLY</li>
758      * <li>ModeCreate: NONE</li>
759      * <li>ModeView: READONLY</li>
760      * <li>ModeEdit: READONLY</li>
761      * <li>ModeSearch: NONE</li>
762      * </ul>
763      *
764      * @param _mode target mode
765      * @return display for the given target mode
766      */
767     public Display getDisplay(final TargetMode _mode)
768     {
769         Display ret = Field.Display.NONE;
770         if (this.mode2display.containsKey(_mode)) {
771             ret = this.mode2display.get(_mode);
772         } else if (_mode.equals(TargetMode.CONNECT) || _mode.equals(TargetMode.VIEW)
773                         || _mode.equals(TargetMode.EDIT)) {
774             ret = Field.Display.READONLY;
775         }
776         return ret;
777     }
778 
779     /**
780      * Getter method for instance variable {@link #classificationName}.
781      *
782      * @return value of instance variable {@link #classificationName}
783      */
784     public String getClassificationName()
785     {
786         return this.classificationName;
787     }
788 
789     /**
790      * Returns for given parameter <i>_id</i> the instance of class
791      * {@link Field}.
792      *
793      * @param _id id to search in the cache
794      * @return instance of class {@link Field}
795      */
796     public static Field get(final long _id)
797     {
798         Field ret = null;
799         final Cache<Long, Field> cache = InfinispanCache.get().<Long, Field>getCache(Field.IDCACHE);
800         if (cache.containsKey(_id)) {
801             ret = cache.get(_id);
802         } else {
803             AbstractCollection col = null;
804             try {
805                 final QueryBuilder queryBldr = new QueryBuilder(CIAdminUserInterface.Field);
806                 queryBldr.addWhereAttrEqValue(CIAdminUserInterface.Field.ID, _id);
807                 final MultiPrintQuery multi = queryBldr.getPrint();
808                 multi.addAttribute(CIAdminUserInterface.Field.Collection);
809                 multi.executeWithoutAccessCheck();
810 
811                 if (multi.next()) {
812                     final Long colId = multi.<Long> getAttribute(CIAdminUserInterface.Field.Collection);
813                     col = Form.get(colId);
814                     if (col == null) {
815                         col = Table.get(colId);
816                     }
817                 }
818             } catch (final EFapsException e) {
819                 Field.LOG.error("get(long)", e);
820             }
821             if (col != null) {
822                 ret = col.getFieldsMap().get(_id);
823                 if (ret != null) {
824                     cache.put(_id, ret);
825                 }
826             }
827         }
828         return ret;
829     }
830 
831     /**
832      * Reset the cache.
833      */
834     public static void initialize()
835     {
836         if (InfinispanCache.get().exists(Field.IDCACHE)) {
837             InfinispanCache.get().<Long, Field>getCache(Field.IDCACHE).clear();
838         } else {
839             InfinispanCache.get().<Long, Field>getCache(Field.IDCACHE);
840             InfinispanCache.get().<Long, Field>getCache(Field.IDCACHE).addListener(new CacheLogListener(Field.LOG));
841         }
842     }
843 
844     /**
845      * {@inheritDoc}
846      */
847     @Override
848     protected void setLinkProperty(final UUID _linkTypeUUID,
849                                    final long _toId,
850                                    final UUID _toTypeUUID,
851                                    final String _toName)
852         throws EFapsException
853     {
854         if (_linkTypeUUID.equals(CIAdminUserInterface.LinkIcon.uuid)) {
855             this.icon = RequestHandler.replaceMacrosInUrl(RequestHandler.URL_IMAGE + _toName);
856         }
857         super.setLinkProperty(_linkTypeUUID, _toId, _toTypeUUID, _toName);
858     }
859 
860     /**
861      * The instance method sets a new property value.
862      *
863      * @param _name name of the property
864      * @param _value value of the property
865      * @throws CacheReloadException on problems with the cache
866      */
867     @Override
868     protected void setProperty(final String _name,
869                                final String _value)
870         throws CacheReloadException
871     {
872         if ("Align".equals(_name)) {
873             this.align = _value;
874         } else if ("ClassNameUI".equals(_name)) {
875             try {
876                 this.classUI = (UIInterface) Class.forName(_value).newInstance();
877             } catch (final ClassNotFoundException e) {
878                 throw new CacheReloadException("could not found class '" + _value + "' for '" + getName() + "'", e);
879             } catch (final InstantiationException e) {
880                 throw new CacheReloadException("could not instantiate class '" + _value + "' for '" + getName() + "'",
881                                 e);
882             } catch (final IllegalAccessException e) {
883                 throw new CacheReloadException("could not access class '" + _value + "' for '" + getName() + "'", e);
884             }
885         } else if ("UIProvider".equals(_name)) {
886             try {
887                 this.uiProvider = (IUIProvider) Class.forName(_value).newInstance();
888             } catch (final ClassNotFoundException e) {
889                 throw new CacheReloadException("could not found class '" + _value + "' for '" + getName() + "'", e);
890             } catch (final InstantiationException e) {
891                 throw new CacheReloadException("could not instantiate class '" + _value + "' for '" + getName() + "'",
892                                 e);
893             } catch (final IllegalAccessException e) {
894                 throw new CacheReloadException("could not access class '" + _value + "' for '" + getName() + "'", e);
895             }
896         } else if ("Columns".equals(_name)) {
897             this.cols = Integer.parseInt(_value);
898         } else if ("Classification".equals(_name)) {
899             this.classificationName = _value;
900         } else if ("CreateValue".equals(_name)) {
901             this.createValue = _value;
902         } else if ("SelectAlternateOID".equals(_name)) {
903             this.selectAlternateOID = _value;
904         } else if ("Select".equals(_name)) {
905             this.select = _value;
906         } else if ("Attribute".equals(_name)) {
907             this.attribute = _value;
908         } else if ("Phrase".equals(_name)) {
909             this.phrase = _value;
910         } else if ("MsgPhrase".equals(_name)) {
911             this.msgPhrase = _value;
912         } else if ("Width".equals(_name)) {
913             setWidth(_value);
914         } else if ("SortAble".equals(_name)) {
915             this.sortAble = !"false".equals(_value);
916         } else if ("FilterBase".equals(_name)) {
917             this.filter.evalBase(_value);
918         } else if ("FilterDefault".equals(_name)) {
919             this.filter.setDefaultValue(_value.trim());
920         } else if ("FilterType".equals(_name)) {
921             this.filter.evalType(_value);
922         } else if ("FilterRequired".equals(_name)) {
923             this.filter.setRequired("TRUE".equalsIgnoreCase(_value));
924         } else if ("FilterAttributes".equals(_name)) {
925             this.filter.setAttributes(_value);
926         } else if ("HideLabel".equals(_name)) {
927             this.hideLabel = "true".equals(_value);
928         } else if ("HRef".equals(_name)) {
929             this.reference = RequestHandler.replaceMacrosInUrl(_value);
930         } else if ("Icon".equals(_name)) {
931             this.icon = RequestHandler.replaceMacrosInUrl(_value);
932         } else if ("Label".equals(_name)) {
933             this.label = _value;
934         } else if ("ModeConnect".equals(_name)) {
935             this.mode2display.put(TargetMode.CONNECT, Field.Display.valueOf(_value.toUpperCase()));
936         } else if ("ModeCreate".equals(_name)) {
937             this.mode2display.put(TargetMode.CREATE, Field.Display.valueOf(_value.toUpperCase()));
938         } else if ("ModeEdit".equals(_name)) {
939             this.mode2display.put(TargetMode.EDIT, Field.Display.valueOf(_value.toUpperCase()));
940         } else if ("ModePrint".equals(_name)) {
941             this.mode2display.put(TargetMode.PRINT, Field.Display.valueOf(_value.toUpperCase()));
942         } else if ("ModeSearch".equals(_name)) {
943             this.mode2display.put(TargetMode.SEARCH, Field.Display.valueOf(_value.toUpperCase()));
944         } else if ("ModeView".equals(_name)) {
945             this.mode2display.put(TargetMode.VIEW, Field.Display.valueOf(_value.toUpperCase()));
946         } else if ("Required".equals(_name)) {
947             this.required = "true".equalsIgnoreCase(_value);
948         } else if ("Rows".equals(_name)) {
949             this.rows = Integer.parseInt(_value);
950         } else if ("RowSpan".equals(_name)) {
951             this.rowSpan = Integer.parseInt(_value);
952         } else if ("ShowTypeIcon".equals(_name)) {
953             this.showTypeIcon = "true".equalsIgnoreCase(_value);
954         } else if ("ShowNumbering".equals(_name)) {
955             this.showNumbering = "true".equalsIgnoreCase(_value);
956         } else if ("Target".equals(_name)) {
957             if ("content".equals(_value)) {
958                 this.target = Target.CONTENT;
959             } else if ("hidden".equals(_value)) {
960                 this.target = Target.HIDDEN;
961             } else if ("popup".equals(_value)) {
962                 this.target = Target.POPUP;
963             }
964         } else {
965             super.setProperty(_name, _value);
966         }
967     }
968 
969     @Override
970     public boolean equals(final Object _obj)
971     {
972         boolean ret;
973         if (_obj instanceof Field) {
974             ret = ((Field) _obj).getId() == getId();
975         } else {
976             ret = super.equals(_obj);
977         }
978         return ret;
979     }
980 
981     @Override
982     public int hashCode()
983     {
984         return  Long.valueOf(getId()).intValue();
985     }
986 }