View Javadoc

1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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  package org.kuali.rice.core.api.uif;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.CoreConstants;
20  import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
21  import org.kuali.rice.core.api.mo.ModelBuilder;
22  import org.w3c.dom.Element;
23  
24  import javax.xml.bind.annotation.XmlAccessType;
25  import javax.xml.bind.annotation.XmlAccessorType;
26  import javax.xml.bind.annotation.XmlAnyElement;
27  import javax.xml.bind.annotation.XmlElement;
28  import javax.xml.bind.annotation.XmlElementWrapper;
29  import javax.xml.bind.annotation.XmlElements;
30  import javax.xml.bind.annotation.XmlRootElement;
31  import javax.xml.bind.annotation.XmlType;
32  import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
33  import java.util.ArrayList;
34  import java.util.Collection;
35  import java.util.Collections;
36  import java.util.List;
37  
38  /**
39   * @see RemotableAttributeFieldContract for more info.
40   */
41  @XmlRootElement(name = RemotableAttributeField.Constants.ROOT_ELEMENT_NAME)
42  @XmlAccessorType(XmlAccessType.NONE)
43  @XmlType(name = RemotableAttributeField.Constants.TYPE_NAME, propOrder = {
44  		RemotableAttributeField.Elements.NAME,
45  		RemotableAttributeField.Elements.DATA_TYPE,
46  		RemotableAttributeField.Elements.SHORT_LABEL,
47  		RemotableAttributeField.Elements.LONG_LABEL,
48  		RemotableAttributeField.Elements.HELP_SUMMARY,
49  		RemotableAttributeField.Elements.CONSTRAINT_TEXT,
50  		RemotableAttributeField.Elements.HELP_DESCRIPTION,
51  		RemotableAttributeField.Elements.FORCE_UPPERCASE,
52  		RemotableAttributeField.Elements.MIN_LENGTH,
53  		RemotableAttributeField.Elements.MAX_LENGTH,
54  		RemotableAttributeField.Elements.MIN_VALUE,
55  		RemotableAttributeField.Elements.MAX_VALUE,
56  		RemotableAttributeField.Elements.REGEX_CONSTRAINT,
57  		RemotableAttributeField.Elements.REGEX_CONSTRAINT_MSG,
58          RemotableAttributeField.Elements.FORMATTER_NAME,
59  		RemotableAttributeField.Elements.REQUIRED,
60  		RemotableAttributeField.Elements.DEFAULT_VALUES,
61          RemotableAttributeField.Elements.ATTRIBUTE_LOOKUP_SETTINGS,
62  		RemotableAttributeField.Elements.CONTROL,
63  		RemotableAttributeField.Elements.WIDGETS,
64  		CoreConstants.CommonElements.FUTURE_ELEMENTS })
65  public final class RemotableAttributeField extends AbstractDataTransferObject implements RemotableAttributeFieldContract {
66  
67      @XmlElement(name = Elements.NAME, required = true)
68      private final String name;
69  
70      @XmlJavaTypeAdapter(DataType.Adapter.class)
71      @XmlElement(name = Elements.DATA_TYPE, required = false)
72      private final String dataType;
73  
74      @XmlElement(name = Elements.SHORT_LABEL, required = false)
75      private final String shortLabel;
76  
77      @XmlElement(name = Elements.LONG_LABEL, required = false)
78      private final String longLabel;
79  
80      @XmlElement(name = Elements.HELP_SUMMARY, required = false)
81      private final String helpSummary;
82  
83      @XmlElement(name = Elements.CONSTRAINT_TEXT, required = false)
84      private final String constraintText;
85  
86      @XmlElement(name = Elements.HELP_DESCRIPTION, required = false)
87      private final String helpDescription;
88  
89      @XmlElement(name = Elements.FORCE_UPPERCASE, required = false)
90      private final boolean forceUpperCase;
91  
92      @XmlElement(name = Elements.MIN_LENGTH, required = false)
93      private final Integer minLength;
94  
95      @XmlElement(name = Elements.MAX_LENGTH, required = false)
96      private final Integer maxLength;
97  
98      @XmlElement(name = Elements.MIN_VALUE, required = false)
99      private final Double minValue;
100 
101     @XmlElement(name = Elements.MAX_VALUE, required = false)
102     private final Double maxValue;
103 
104     @XmlElement(name = Elements.REGEX_CONSTRAINT, required = false)
105     private final String regexConstraint;
106 
107     @XmlElement(name = Elements.REGEX_CONSTRAINT_MSG, required = false)
108     private final String regexContraintMsg;
109 
110     @XmlElement(name = Elements.FORMATTER_NAME, required = false)
111     private final String formatterName;
112 
113     @XmlElement(name = Elements.REQUIRED, required = false)
114     private final boolean required;
115 
116     @XmlElementWrapper(name = Elements.DEFAULT_VALUES, required = false)
117     @XmlElement(name = Elements.DEFAULT_VALUE, required = false)
118     private final Collection<String> defaultValues;
119 
120     @XmlElement(name = Elements.ATTRIBUTE_LOOKUP_SETTINGS, required = false)
121     private final RemotableAttributeLookupSettings attributeLookupSettings;
122 
123     @XmlElements(value = {
124         @XmlElement(name = RemotableCheckbox.Constants.ROOT_ELEMENT_NAME, type = RemotableCheckbox.class, required = false),
125         @XmlElement(name = RemotableCheckboxGroup.Constants.ROOT_ELEMENT_NAME, type = RemotableCheckboxGroup.class, required = false),
126         @XmlElement(name = RemotableHiddenInput.Constants.ROOT_ELEMENT_NAME, type = RemotableHiddenInput.class, required = false),
127         @XmlElement(name = RemotablePasswordInput.Constants.ROOT_ELEMENT_NAME, type = RemotablePasswordInput.class, required = false),
128         @XmlElement(name = RemotableRadioButtonGroup.Constants.ROOT_ELEMENT_NAME, type = RemotableRadioButtonGroup.class, required = false),
129         @XmlElement(name = RemotableSelect.Constants.ROOT_ELEMENT_NAME, type = RemotableSelect.class, required = false),
130         @XmlElement(name = RemotableTextarea.Constants.ROOT_ELEMENT_NAME, type = RemotableTextarea.class, required = false),
131         @XmlElement(name = RemotableTextInput.Constants.ROOT_ELEMENT_NAME, type = RemotableTextInput.class, required = false)
132     })
133     // this field is defaulted to a RemotableTextInput in constructors and builder
134     // for flexibility, i would have preferred to assign a default value on the client/consumer only but there isn't a practical way to do that
135     private final RemotableAbstractControl control;
136 
137     @XmlElementWrapper(name = Elements.WIDGETS, required = false)
138     @XmlElements(value = {
139         @XmlElement(name = RemotableDatepicker.Constants.ROOT_ELEMENT_NAME, type = RemotableDatepicker.class, required = false),
140         @XmlElement(name = RemotableQuickFinder.Constants.ROOT_ELEMENT_NAME, type = RemotableQuickFinder.class, required = false),
141         @XmlElement(name = RemotableTextExpand.Constants.ROOT_ELEMENT_NAME, type = RemotableTextExpand.class, required = false)
142     })
143     private final Collection<? extends RemotableAbstractWidget> widgets;
144 
145     @SuppressWarnings("unused")
146     @XmlAnyElement
147     private final Collection<Element> _futureElements = null;
148 
149     /**
150      * Should only be invoked by JAXB.
151      */
152     @SuppressWarnings("unused")
153     private RemotableAttributeField() {
154         this.name = null;
155         this.dataType = null;
156         this.shortLabel = null;
157         this.longLabel = null;
158         this.helpSummary = null;
159         this.constraintText = null;
160         this.helpDescription = null;
161         this.forceUpperCase = false;
162         this.minLength = null;
163         this.maxLength = null;
164         this.minValue = null;
165         this.maxValue = null;
166         this.regexConstraint = null;
167         this.regexContraintMsg = null;
168         this.formatterName = null;
169         this.required = false;
170         this.defaultValues = null;
171         this.attributeLookupSettings = null;
172         this.control = RemotableTextInput.Builder.create().build();
173         this.widgets = null;
174     }
175 
176     private RemotableAttributeField(Builder b) {
177         this.name = b.name;
178         if (b.dataType == null) {
179             this.dataType = null;
180         } else {
181             this.dataType = b.dataType.name();
182         }
183         this.shortLabel = b.shortLabel;
184         this.longLabel = b.longLabel;
185         this.helpSummary = b.helpSummary;
186         this.constraintText = b.helpConstraint;
187         this.helpDescription = b.helpDescription;
188         this.forceUpperCase = b.forceUpperCase;
189         this.minLength = b.minLength;
190         this.maxLength = b.maxLength;
191         this.minValue = b.minValue;
192         this.maxValue = b.maxValue;
193         this.regexConstraint = b.regexConstraint;
194         this.regexContraintMsg = b.regexContraintMsg;
195         this.formatterName = b.formatterName;
196         this.required = b.required;
197         if (b.defaultValues == null) {
198             this.defaultValues = Collections.emptyList();
199         } else {
200             List<String> defaultValuesCopy = new ArrayList<String>(b.defaultValues);
201             this.defaultValues = Collections.unmodifiableList(defaultValuesCopy);
202         }
203         if (b.attributeLookupSettings == null) {
204             this.attributeLookupSettings = null;
205         } else {
206             this.attributeLookupSettings = b.attributeLookupSettings.build();
207         }
208         if (b.control == null) {
209             this.control = RemotableTextInput.Builder.create().build();
210         } else {
211             this.control = b.control.build();
212         }
213 
214         final List<RemotableAbstractWidget> temp = new ArrayList<RemotableAbstractWidget>();
215         if (b.widgets != null) {
216             for (RemotableAbstractWidget.Builder attr : b.widgets) {
217                 temp.add(attr.build());
218             }
219         }
220         this.widgets = Collections.unmodifiableList(temp);
221     }
222 
223     @Override
224     public String getName() {
225         return name;
226     }
227 
228     @Override
229     public DataType getDataType() {
230         if (dataType == null) {
231             return null;
232         }
233         return DataType.valueOf(dataType);
234     }
235 
236     @Override
237     public String getShortLabel() {
238         return shortLabel;
239     }
240 
241     @Override
242     public String getLongLabel() {
243         return longLabel;
244     }
245 
246     @Override
247     public String getHelpSummary() {
248         return helpSummary;
249     }
250 
251     @Override
252     public String getConstraintText() {
253         return constraintText;
254     }
255 
256     @Override
257     public String getHelpDescription() {
258         return helpDescription;
259     }
260 
261     @Override
262     public boolean isForceUpperCase() {
263         return forceUpperCase;
264     }
265 
266     @Override
267     public Integer getMinLength() {
268         return minLength;
269     }
270 
271     @Override
272     public Integer getMaxLength() {
273         return maxLength;
274     }
275 
276     @Override
277     public Double getMinValue() {
278         return minValue;
279     }
280 
281     @Override
282     public Double getMaxValue() {
283         return maxValue;
284     }
285 
286     @Override
287     public String getRegexConstraint() {
288         return regexConstraint;
289     }
290 
291     @Override
292     public String getRegexContraintMsg() {
293         return regexContraintMsg;
294     }
295 
296     @Override
297     public String getFormatterName() {
298         return formatterName;
299     }
300     @Override
301     public boolean isRequired() {
302         return required;
303     }
304 
305     @Override
306     public Collection<String> getDefaultValues() {
307         return defaultValues;
308     }
309 
310     @Override
311     public RemotableControlContract getControl() {
312         return control;
313     }
314 
315     @Override
316     public Collection<? extends RemotableAbstractWidget> getWidgets() {
317         return widgets;
318     }
319 
320     @Override
321     public AttributeLookupSettings getAttributeLookupSettings() {
322         return attributeLookupSettings;
323     }
324 
325     /**
326      * Utility method to search a collection of attribute fields and returns
327      * a field for a give attribute name.
328      *
329      * @param attributeName the name of the attribute to search for.  Cannot be blank or null.
330      * @param fields cannot be null.
331      *
332      * @return the attribute field or null if not found.
333      */
334     public static RemotableAttributeField findAttribute(String attributeName, Collection<RemotableAttributeField> fields) {
335         if (StringUtils.isBlank(attributeName)) {
336             throw new IllegalArgumentException("attributeName is blank");
337         }
338 
339         if (fields == null) {
340             throw new IllegalArgumentException("errors is null");
341         }
342 
343         for (RemotableAttributeField field : fields) {
344             if (attributeName.equals(field.getName())) {
345                 return field;
346             }
347         }
348         return null;
349     }
350     
351     public static final class Builder implements RemotableAttributeFieldContract, ModelBuilder {
352         private String name;
353         private DataType dataType;
354         private String shortLabel;
355         private String longLabel;
356 
357         private String helpSummary;
358         private String helpConstraint;
359         private String helpDescription;
360 
361         private boolean forceUpperCase;
362 
363         private Integer minLength;
364         private Integer maxLength;
365 
366         private Double minValue;
367         private Double maxValue;
368         private String regexConstraint;
369         private String regexContraintMsg;
370 
371         private String formatterName;
372         private boolean required;
373 
374         private Collection<String> defaultValues = new ArrayList<String>();
375         private RemotableAttributeLookupSettings.Builder attributeLookupSettings;
376         private RemotableAbstractControl.Builder control =  RemotableTextInput.Builder.create();
377 
378         private Collection<RemotableAbstractWidget.Builder> widgets = new ArrayList<RemotableAbstractWidget.Builder>();
379 
380         private Builder(String name) {
381             setName(name);
382         }
383 
384         public static Builder create(String name) {
385             return new Builder(name);
386         }
387 
388         public static Builder create(RemotableAttributeFieldContract field) {
389             if (field == null) {
390                 throw new IllegalArgumentException("field was null");
391             }
392 
393             Builder b = new Builder(field.getName());
394             b.setDataType(field.getDataType());
395             b.setShortLabel(field.getShortLabel());
396             b.setLongLabel(field.getLongLabel());
397             b.setHelpSummary(field.getHelpSummary());
398             b.setConstraintText(field.getConstraintText());
399             b.setHelpDescription(field.getHelpDescription());
400             b.setForceUpperCase(field.isForceUpperCase());
401             b.setMinLength(field.getMinLength());
402             b.setMaxLength(field.getMaxLength());
403             b.setMinValue(field.getMinValue());
404             b.setMaxValue(field.getMaxValue());
405             b.setRegexConstraint(field.getRegexConstraint());
406             b.setRegexContraintMsg(field.getRegexContraintMsg());
407             b.setFormatterName(field.getFormatterName());
408             b.setRequired(field.isRequired());
409             b.setDefaultValues(field.getDefaultValues());
410             if (field.getAttributeLookupSettings() != null) {
411                 b.setAttributeLookupSettings(RemotableAttributeLookupSettings.Builder.create(
412                         field.getAttributeLookupSettings()));
413             }
414             if (field.getControl() != null) {
415                 b.setControl(ControlCopy.toBuilder(field.getControl()));
416             }
417 
418             final List<RemotableAbstractWidget.Builder> temp = new ArrayList<RemotableAbstractWidget.Builder>();
419             if (field.getWidgets() != null) {
420                 for (RemotableWidgetContract w : field.getWidgets()) {
421                     temp.add(WidgetCopy.toBuilder(w));
422                 }
423             }
424             b.setWidgets(temp);
425 
426             return b;
427         }
428 
429         @Override
430         public String getName() {
431             return name;
432         }
433 
434         public void setName(String name) {
435             if (StringUtils.isBlank(name)) {
436                 throw new IllegalArgumentException("name is blank");
437             }
438 
439             this.name = name;
440         }
441 
442         @Override
443         public DataType getDataType() {
444             return dataType;
445         }
446 
447         public void setDataType(DataType dataType) {
448             this.dataType = dataType;
449         }
450 
451         @Override
452         public String getShortLabel() {
453             return shortLabel;
454         }
455 
456         public void setShortLabel(String shortLabel) {
457             this.shortLabel = shortLabel;
458         }
459 
460         @Override
461         public String getLongLabel() {
462             return longLabel;
463         }
464 
465         public void setLongLabel(String longLabel) {
466             this.longLabel = longLabel;
467         }
468 
469         @Override
470         public String getHelpSummary() {
471             return helpSummary;
472         }
473 
474         public void setHelpSummary(String helpSummary) {
475             this.helpSummary = helpSummary;
476         }
477 
478         @Override
479         public String getConstraintText() {
480             return helpConstraint;
481         }
482 
483         public void setConstraintText(String helpConstraint) {
484             this.helpConstraint = helpConstraint;
485         }
486 
487         @Override
488         public String getHelpDescription() {
489             return helpDescription;
490         }
491 
492         public void setHelpDescription(String helpDescription) {
493             this.helpDescription = helpDescription;
494         }
495 
496         @Override
497         public boolean isForceUpperCase() {
498             return forceUpperCase;
499         }
500 
501         public void setForceUpperCase(boolean forceUpperCase) {
502             this.forceUpperCase = forceUpperCase;
503         }
504 
505         @Override
506         public Integer getMinLength() {
507             return minLength;
508         }
509 
510         public void setMinLength(Integer minLength) {
511             if (minLength != null && minLength < 1) {
512                 throw new IllegalArgumentException("minLength was < 1");
513             }
514             
515             this.minLength = minLength;
516         }
517 
518         @Override
519         public Integer getMaxLength() {
520             return maxLength;
521         }
522 
523         public void setMaxLength(Integer maxLength) {
524             if (maxLength != null && maxLength < 1) {
525                 throw new IllegalArgumentException("maxLength was < 1");
526             }
527             
528             this.maxLength = maxLength;
529         }
530 
531         @Override
532         public Double getMinValue() {
533             return minValue;
534         }
535 
536         public void setMinValue(Double minValue) {
537             this.minValue = minValue;
538         }
539 
540         @Override
541         public Double getMaxValue() {
542             return maxValue;
543         }
544 
545         public void setMaxValue(Double maxValue) {
546             this.maxValue = maxValue;
547         }
548 
549         @Override
550         public String getRegexConstraint() {
551             return regexConstraint;
552         }
553 
554         public void setRegexConstraint(String regexConstraint) {
555             this.regexConstraint = regexConstraint;
556         }
557 
558         @Override
559         public String getRegexContraintMsg() {
560             return regexContraintMsg;
561         }
562 
563         public void setRegexContraintMsg(String regexContraintMsg) {
564             this.regexContraintMsg = regexContraintMsg;
565         }
566 
567         @Override
568         public String getFormatterName() {
569            return formatterName;
570         }
571 
572         public void setFormatterName(String formatterName) {
573            this.formatterName = formatterName;
574         }
575 
576         @Override
577         public boolean isRequired() {
578             return required;
579         }
580 
581         public void setRequired(boolean required) {
582             this.required = required;
583         }
584 
585         @Override
586         public Collection<String> getDefaultValues() {
587             return defaultValues;
588         }
589 
590         public void setDefaultValues(Collection<String> defaultValues) {
591             this.defaultValues = defaultValues;
592         }
593 
594         public void addToDefaultValues(String defaultValue) {
595             this.defaultValues.add(defaultValue);
596         }
597 
598         @Override
599         public RemotableAttributeLookupSettings.Builder getAttributeLookupSettings() {
600             return attributeLookupSettings;
601         }
602 
603         public void setAttributeLookupSettings(RemotableAttributeLookupSettings.Builder attributeLookupSettings) {
604             this.attributeLookupSettings = attributeLookupSettings;
605         }
606 
607         @Override
608         public RemotableAbstractControl.Builder getControl() {
609             return control;
610         }
611 
612         public void setControl(RemotableAbstractControl.Builder control) {
613             this.control = control;
614         }
615 
616         @Override
617         public Collection<RemotableAbstractWidget.Builder> getWidgets() {
618             return widgets;
619         }
620 
621         public void setWidgets(Collection<RemotableAbstractWidget.Builder> widgets) {
622             this.widgets = widgets;
623         }
624 
625         @Override
626         public RemotableAttributeField build() {
627             return new RemotableAttributeField(this);
628         }
629     }
630 
631     /**
632      * Defines some internal constants used on this class.
633      */
634     static final class Constants {
635         static final String TYPE_NAME = "AttributeFieldType";
636         final static String ROOT_ELEMENT_NAME = "attributeField";
637     }
638 
639     static final class Elements {
640         static final String NAME = "name";
641         static final String DATA_TYPE = "dataType";
642         static final String SHORT_LABEL = "shortLabel";
643         static final String LONG_LABEL = "longLabel";
644         static final String HELP_SUMMARY = "helpSummary";
645         static final String CONSTRAINT_TEXT = "constraintText";
646         static final String HELP_DESCRIPTION = "helpDescription";
647         static final String FORCE_UPPERCASE = "forceUpperCase";
648         static final String MIN_LENGTH = "minLength";
649         static final String MAX_LENGTH = "maxLength";
650         static final String MIN_VALUE = "minValue";
651         static final String MAX_VALUE = "maxValue";
652         static final String REGEX_CONSTRAINT = "regexConstraint";
653         static final String REGEX_CONSTRAINT_MSG = "regexContraintMsg";
654         static final String FORMATTER_NAME = "formatterName";
655         static final String REQUIRED = "required";
656         static final String DEFAULT_VALUES = "defaultValues";
657         static final String DEFAULT_VALUE = "defaultValue";
658         static final String ATTRIBUTE_LOOKUP_SETTINGS = "attributeLookupSettings";
659         static final String CONTROL = "control";
660         static final String WIDGETS = "widgets";
661     }
662 }