View Javadoc
1   /**
2    * Copyright 2005-2016 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.kns.datadictionary;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.kns.service.BusinessObjectMetaDataService;
20  import org.kuali.rice.kns.service.KNSServiceLocator;
21  import org.kuali.rice.krad.datadictionary.DataDictionary;
22  import org.kuali.rice.krad.datadictionary.DataDictionaryDefinitionBase;
23  import org.kuali.rice.krad.datadictionary.RelationshipDefinition;
24  import org.kuali.rice.krad.datadictionary.exception.AttributeValidationException;
25  import org.kuali.rice.krad.datadictionary.exception.ClassValidationException;
26  import org.kuali.rice.krad.datadictionary.mask.Mask;
27  import org.kuali.rice.krad.valuefinder.ValueFinder;
28  
29  /**
30   * Contains field-related information for DataDictionary entries.  Used by lookups and inquiries.
31   *
32   * Note: the setters do copious amounts of validation, to facilitate generating errors during the parsing process.
33   *
34   * @deprecated Use {@link org.kuali.rice.krad.uif.field.Field} subclasses.
35   */
36  @Deprecated
37  public class FieldDefinition extends DataDictionaryDefinitionBase implements FieldDefinitionI {
38      private static final long serialVersionUID = -3426603523049661524L;
39      
40  	protected String attributeName;
41      protected boolean required = false;
42      protected boolean forceInquiry = false;
43      protected boolean noInquiry = false;
44      protected boolean noDirectInquiry = false;
45      protected boolean forceLookup = false;
46      protected boolean noLookup = false;
47      protected boolean useShortLabel = false;
48      protected String defaultValue;
49      protected Class<? extends ValueFinder> defaultValueFinderClass;
50      protected String quickfinderParameterString;
51      protected Class<? extends ValueFinder> quickfinderParameterStringBuilderClass;
52  
53      protected Integer maxLength = null;
54  
55      protected String displayEditMode;
56      protected Mask displayMask;
57  
58  	protected boolean hidden 	= false;
59  	protected boolean readOnly 	= false;
60  
61  	protected boolean treatWildcardsAndOperatorsAsLiteral = false;
62  	
63      protected String alternateDisplayAttributeName;
64      protected String additionalDisplayAttributeName;
65  	
66  	protected boolean triggerOnChange;
67  	protected boolean total = false;
68  	
69      public FieldDefinition() {
70      }
71  
72  
73      /**
74       * @return attributeName
75       */
76      public String getAttributeName() {
77          return attributeName;
78      }
79  
80      /**
81       * Sets attributeName to the given value.
82       *
83       * @param attributeName
84       * @throws IllegalArgumentException if the given attributeName is blank
85       */
86      public void setAttributeName(String attributeName) {
87          if (StringUtils.isBlank(attributeName)) {
88              throw new IllegalArgumentException("invalid (blank) attributeName");
89          }
90          this.attributeName = attributeName;
91      }
92  
93  
94      /**
95       * @return true if this attribute is required
96       */
97      public boolean isRequired() {
98          return required;
99      }
100 
101 
102     /**
103                     required = true means that the user must enter something
104                         into the search criterion lookup field
105      */
106     public void setRequired(boolean required) {
107         this.required = required;
108     }
109 
110 
111     /**
112      * @return Returns the forceInquiry.
113      */
114     public boolean isForceInquiry() {
115         return forceInquiry;
116     }
117 
118 
119     /**
120      * forceInquiry = true means that the displayed field value will
121                     always be made inquirable (this attribute is not used within the code).
122      */
123     public void setForceInquiry(boolean forceInquiry) {
124         this.forceInquiry = forceInquiry;
125     }
126 
127     /**
128      * @return Returns the forceLookup.
129      */
130     public boolean isForceLookup() {
131         return forceLookup;
132     }
133 
134     /**
135      * forceLookup = this attribute is not used
136      */
137     public void setForceLookup(boolean forceLookup) {
138         this.forceLookup = forceLookup;
139     }
140 
141     /**
142      * @return Returns the noInquiry.
143      */
144     public boolean isNoInquiry() {
145         return noInquiry;
146     }
147 
148     /**
149      * @return Returns a boolean value indicating whether or not to provide
150      *          a direct inquiry for the lookup field
151      */
152     public boolean isNoDirectInquiry()
153     {
154         return noDirectInquiry;
155     }
156 
157     /**
158      * noInquiry = true means that the displayed field will never be made inquirable.
159      */
160     public void setNoInquiry(boolean noInquiry) {
161         this.noInquiry = noInquiry;
162     }
163 
164     /**
165      * @param noInquiry If true, the displayed field will not have a direct
166 	 *     inquiry facility
167      */
168     public void setNoDirectInquiry(boolean noDirectInquiry) {
169         this.noDirectInquiry = noDirectInquiry;
170     }
171 
172     /**
173      * @return Returns the noLookup.
174      */
175     public boolean isNoLookup() {
176         return noLookup;
177     }
178 
179     /**
180      * noLookup = true means that field should not include magnifying glass (i.e. quickfinder)
181      */
182     public void setNoLookup(boolean noLookup) {
183         this.noLookup = noLookup;
184     }
185 
186 
187     /**
188 	 * @return the useShortLabel
189 	 */
190 	public boolean isUseShortLabel() {
191 		return this.useShortLabel;
192 	}
193 
194 
195 	/**
196 	 * @param useShortLabel the useShortLabel to set
197 	 */
198 	public void setUseShortLabel(boolean useShortLabel) {
199 		this.useShortLabel = useShortLabel;
200 	}
201 
202 
203 	/**
204      * @return Returns the defaultValue.
205      */
206     public String getDefaultValue() {
207         return defaultValue;
208     }
209 
210 
211     /**
212            The defaultValue element will pre-load the specified value
213            into the field.
214      */
215     public void setDefaultValue(String defaultValue) {
216         this.defaultValue = defaultValue;
217     }
218 
219     /**
220 	 * the quickfinderParameterString is a comma separated list of parameter/value pairs, of the format
221 	 * "param1=value1,param2=value2", where the parameters correspond to attributes of the target class
222 	 * for the quickfinder, and the values to literals that those attributes will default to when the
223 	 * quickfinder is used.
224 	 * @return the quickfinderParameterString
225 	 */
226 	public String getQuickfinderParameterString() {
227 		return this.quickfinderParameterString;
228 	}
229 
230 	/**
231 	 * @param quickfinderParameterString the quickfinderParameterString to set.  See {@link #getQuickfinderParameterString()}
232 	 */
233 	public void setQuickfinderParameterString(String quickfinderParameterString) {
234 		this.quickfinderParameterString = quickfinderParameterString;
235 	}
236 
237 
238     /**
239      * the quickfinderParameterStringBuilderClass specifies the java class that will be used
240      * to determine the default value(s) for field(s) on the target lookup when the quickfinder
241      * is used. The classname specified in this field must implement
242      * {@link org.kuali.rice.krad.valuefinder.ValueFinder}.  See {@link #getQuickfinderParameterString()}
243      * for the result string format.
244 	 * @return the quickfinderParameterStringBuilderClass
245 	 */
246 	public Class<? extends ValueFinder> getQuickfinderParameterStringBuilderClass() {
247 		return this.quickfinderParameterStringBuilderClass;
248 	}
249 
250     /**
251      * See {@link #getQuickfinderParameterStringBuilderClass()}
252 	 * @param quickfinderParameterStringBuilderClass the quickfinderParameterStringBuilderClass to set
253      */
254 	public void setQuickfinderParameterStringBuilderClass(
255 			Class<? extends ValueFinder> quickfinderParameterStringBuilderClass) {
256         if (quickfinderParameterStringBuilderClass == null) {
257             throw new IllegalArgumentException("invalid (null) quickfinderParameterStringBuilderClass");
258         }
259 		this.quickfinderParameterStringBuilderClass = quickfinderParameterStringBuilderClass;
260     }
261 
262     /**
263      * Directly validate simple fields.
264      *
265      * @see org.kuali.rice.krad.datadictionary.DataDictionaryDefinition#completeValidation(java.lang.Class, java.lang.Object)
266      */
267     public void completeValidation(Class rootBusinessObjectClass, Class otherBusinessObjectClass) {
268     	BusinessObjectMetaDataService boMetadataService = KNSServiceLocator.getBusinessObjectMetaDataService();
269 
270         if (!DataDictionary.isPropertyOf(rootBusinessObjectClass, getAttributeName())) {
271             throw new AttributeValidationException("unable to find attribute '" + attributeName + "' in rootBusinessObjectClass '" + rootBusinessObjectClass.getName() + "' (" + "" + ")");
272         }
273 
274         if (StringUtils.isNotBlank(getAlternateDisplayAttributeName())) {
275             if (!DataDictionary.isPropertyOf(rootBusinessObjectClass, getAlternateDisplayAttributeName())) {
276                 throw new AttributeValidationException("unable to find attribute named '" + getName() + "' in rootBusinessObjectClass '" + rootBusinessObjectClass.getName() + "' (" + "" + ")");
277             }
278         }
279         
280         if (StringUtils.isNotBlank(getAdditionalDisplayAttributeName())) {
281             if (!DataDictionary.isPropertyOf(rootBusinessObjectClass, getAdditionalDisplayAttributeName())) {
282                 throw new AttributeValidationException("unable to find attribute named '" + getName() + "' in rootBusinessObjectClass '" + rootBusinessObjectClass.getName() + "' (" + "" + ")");
283             }
284         }
285 
286         if (defaultValueFinderClass != null && defaultValue != null) {
287             throw new AttributeValidationException("Both defaultValue and defaultValueFinderClass can not be specified on attribute " + getAttributeName() + " in rootBusinessObjectClass " + rootBusinessObjectClass.getName());
288         }
289 
290         validateQuickfinderParameters(rootBusinessObjectClass, boMetadataService);
291 
292         if (forceInquiry == true && noInquiry == true) {
293             throw new AttributeValidationException("Both forceInquiry and noInquiry can not be set to true on attribute " + getAttributeName() + " in rootBusinessObjectClass " + rootBusinessObjectClass.getName());
294         }
295         if (forceLookup == true && noLookup == true) {
296             throw new AttributeValidationException("Both forceLookup and noLookup can not be set to true on attribute " + getAttributeName() + " in rootBusinessObjectClass " + rootBusinessObjectClass.getName());
297         }
298     }
299 
300 
301     /**
302 	 * This method does validation on the quickfinderParameterString and quickfinderParameterStringBuilderClass members
303 	 *
304 	 * @param rootBusinessObjectClass
305 	 * @param boMetadataService
306 	 */
307 	private void validateQuickfinderParameters(Class rootBusinessObjectClass,
308 			BusinessObjectMetaDataService boMetadataService) {
309 		if (quickfinderParameterStringBuilderClass != null && quickfinderParameterString != null) {
310             throw new AttributeValidationException("Both quickfinderParameterString and quickfinderParameterStringBuilderClass can not be specified on attribute " + getAttributeName() + " in rootBusinessObjectClass " + rootBusinessObjectClass.getName());
311         }
312 
313         // String used for building exception messages
314         String quickfinderParameterStringSource = "quickfinderParameterString";
315 
316         if (quickfinderParameterStringBuilderClass != null) {
317         	try {
318 		        quickfinderParameterStringSource = "quickfinderParameterStringBuilderClass " + quickfinderParameterStringBuilderClass.getCanonicalName();
319 				quickfinderParameterString = quickfinderParameterStringBuilderClass.newInstance().getValue();
320 			} catch (InstantiationException e) {
321 				throw new ClassValidationException("unable to create new instance of "+  quickfinderParameterStringSource +" while validating rootBusinessObjectClass '"+ rootBusinessObjectClass.getName() +"'", e);
322 			} catch (IllegalAccessException e) {
323 				throw new ClassValidationException("unable to create new instance of "+  quickfinderParameterStringSource +" while validating rootBusinessObjectClass '"+ rootBusinessObjectClass.getName() +"'", e);
324 			}
325         }
326 
327         if (!StringUtils.isEmpty(quickfinderParameterString)) {
328         	// quickfinderParameterString will look something like "campusTypeCode=P,active=Y"
329         	for (String quickfinderParam : quickfinderParameterString.split(",")) { // this is guaranteed to return at least one
330         		if (quickfinderParam.contains("=")) {
331         			String propertyName = quickfinderParam.split("=")[0];
332         			RelationshipDefinition relationship = boMetadataService.getBusinessObjectRelationshipDefinition(rootBusinessObjectClass, attributeName);
333         			Class targetClass = relationship.getTargetClass();
334 
335         			// This is insufficient to ensure the property is valid for a lookup default, but it's better than nothing.
336             		if (!DataDictionary.isPropertyOf(targetClass, propertyName)) {
337             			throw new ClassValidationException("malformed parameter string  '"+ quickfinderParameterString +"' from "+ quickfinderParameterStringSource +
338             					", '"+ propertyName +"' is not a property of "+ targetClass +"' for rootBusinessObjectClass '"+ rootBusinessObjectClass.getName() +"'");
339             		}
340 
341         		} else {
342         			throw new ClassValidationException("malformed parameter string '"+ quickfinderParameterString +"' from "+ quickfinderParameterStringSource +
343         					" for rootBusinessObjectClass '"+ rootBusinessObjectClass.getName() +"'");
344         		}
345         	}
346         }
347 	}
348 
349 
350     /**
351      * @see java.lang.Object#toString()
352      */
353     public String toString() {
354         return "FieldDefinition for attribute " + getAttributeName();
355     }
356 
357 
358     public String getName() {
359         return attributeName;
360     }
361 
362 
363     public String getDisplayEditMode() {
364         return displayEditMode;
365     }
366 
367 
368     /*
369                         The document authorizer classes have a method getEditMode, which is a map of edit mode to
370                         value mappings.  Depending on the context, the value of the mapping may be relevant, and the logic determining
371                         whether the value is relevant is often implemented in the JSP/tag layer.
372 
373                         Fields on a document (particularily maintenance documents) may be associated with
374                         an edit mode.  If the edit mode is mapped to a relevant value, then the all fields associated with the edit mode
375                         will be rendered unhidden.
376 
377                         The displayEditMode element is used to specify the edit mode that will be associated with the field.
378                         If the document authorizer returns a map with this edit mode mapped to a proper value, then the field will be unhidden to the user.
379      */
380     public void setDisplayEditMode(String displayEditMode) {
381         this.displayEditMode = displayEditMode;
382     }
383 
384 
385     public Mask getDisplayMask() {
386         return displayMask;
387     }
388 
389     /**
390      * The displayMask element specifies the type of masking to
391                     be used to hide the value from un-authorized users.
392                     There are three types of masking.
393      */
394     public void setDisplayMask(Mask displayMask) {
395         this.displayMask = displayMask;
396     }
397 
398 
399 
400     public boolean isReadOnlyAfterAdd() {
401         return false;
402     }
403 
404 
405     /**
406      * Gets the maxLength attribute.
407      * @return Returns the maxLength.
408      */
409     public Integer getMaxLength() {
410         return maxLength;
411     }
412 
413 
414     /**
415      * maxLength = the maximum allowable length of the field in the lookup result fields.  In other contexts,
416                     like inquiries, this field has no effect.
417      */
418     public void setMaxLength(Integer maxLength) {
419         this.maxLength = maxLength;
420     }
421 
422     /**
423      * @return custom defaultValue class
424      */
425     public Class<? extends ValueFinder> getDefaultValueFinderClass() {
426         return this.defaultValueFinderClass;
427     }
428 
429     /**
430                       The defaultValueFinderClass specifies the java class that will be
431                       used to determine the default value of a field.  The classname
432                       specified in this field must implement ValueFinder
433      */
434     public void setDefaultValueFinderClass(Class<? extends ValueFinder> defaultValueFinderClass) {
435         if (defaultValueFinderClass == null) {
436             throw new IllegalArgumentException("invalid (null) defaultValueFinderClass");
437         }
438         this.defaultValueFinderClass = defaultValueFinderClass;
439     }
440     
441 	/**
442 	 * @return the hidden
443 	 */
444 	public boolean isHidden() {
445 		return this.hidden;
446 	}
447 
448 	/**
449 	 * @param hidden
450      *  If the ControlDefinition.isHidden == true then a corresponding LookupDefinition would
451      *  automatically be removed from the search criteria.  In some cases you might want the
452      *  hidden field to be used as a search criteria.  For example, in PersonImpl.xml a client
453      *  might want to have the campus code hidden and preset to Bloomington.  So when the search
454      *  is run, only people from the bloomington campus are returned.
455      *
456      *   So, if you want to have a hidden search criteria, set this variable to true. Defaults to
457      *   false.
458      */
459 	public void setHidden(boolean hidden) {
460 		this.hidden = hidden;
461 	}
462 	
463 	/**
464 	 * @return the readOnly
465 	 */
466 	public boolean isReadOnly() {
467 		return this.readOnly;
468 	}
469 	
470 	/**
471 	 * @param readOnly the readOnly to set
472 	 */
473 	public void setReadOnly(boolean readOnly) {
474 		this.readOnly = readOnly;
475 	}
476 	
477 	public boolean isTriggerOnChange() {
478 		return this.triggerOnChange;
479 	}
480 
481 	public void setTriggerOnChange(boolean triggerOnChange) {
482 		this.triggerOnChange = triggerOnChange;
483 	}
484 
485 	/**
486 	 * @return the treatWildcardsAndOperatorsAsLiteralOnLookups
487 	 */
488 	public boolean isTreatWildcardsAndOperatorsAsLiteral() {
489 		return this.treatWildcardsAndOperatorsAsLiteral;
490 	}
491 
492 
493 	/**
494 	 * @param treatWildcardsAndOperatorsAsLiteralOnLookups the treatWildcardsAndOperatorsAsLiteralOnLookups to set
495 	 */
496 	public void setTreatWildcardsAndOperatorsAsLiteral(
497 			boolean treatWildcardsAndOperatorsAsLiteralOnLookups) {
498 		this.treatWildcardsAndOperatorsAsLiteral = treatWildcardsAndOperatorsAsLiteralOnLookups;
499 	}
500 
501 
502 	public String getAlternateDisplayAttributeName() {
503 		return this.alternateDisplayAttributeName;
504 	}
505 
506 
507 	public void setAlternateDisplayAttributeName(String alternateDisplayAttributeName) {
508 		this.alternateDisplayAttributeName = alternateDisplayAttributeName;
509 	}
510 
511 
512 	public String getAdditionalDisplayAttributeName() {
513 		return this.additionalDisplayAttributeName;
514 	}
515 
516 
517 	public void setAdditionalDisplayAttributeName(String additionalDisplayAttributeName) {
518 		this.additionalDisplayAttributeName = additionalDisplayAttributeName;
519 	}
520 
521 
522 	public boolean isTotal() {
523 		return this.total;
524 	}
525 
526 
527 	public void setTotal(boolean total) {
528 		this.total = total;
529 	}
530 	
531 }