001 /**
002 * Copyright 2005-2013 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.kns.datadictionary;
017
018 import org.apache.commons.lang.StringUtils;
019 import org.kuali.rice.kns.service.BusinessObjectMetaDataService;
020 import org.kuali.rice.kns.service.KNSServiceLocator;
021 import org.kuali.rice.krad.datadictionary.DataDictionary;
022 import org.kuali.rice.krad.datadictionary.DataDictionaryDefinitionBase;
023 import org.kuali.rice.krad.datadictionary.RelationshipDefinition;
024 import org.kuali.rice.krad.datadictionary.exception.AttributeValidationException;
025 import org.kuali.rice.krad.datadictionary.exception.ClassValidationException;
026 import org.kuali.rice.krad.datadictionary.mask.Mask;
027 import org.kuali.rice.krad.valuefinder.ValueFinder;
028
029 /**
030 * Contains field-related information for DataDictionary entries. Used by lookups and inquiries.
031 *
032 * Note: the setters do copious amounts of validation, to facilitate generating errors during the parsing process.
033 */
034 @Deprecated
035 public class FieldDefinition extends DataDictionaryDefinitionBase implements FieldDefinitionI {
036 private static final long serialVersionUID = -3426603523049661524L;
037
038 protected String attributeName;
039 protected boolean required = false;
040 protected boolean forceInquiry = false;
041 protected boolean noInquiry = false;
042 protected boolean noDirectInquiry = false;
043 protected boolean forceLookup = false;
044 protected boolean noLookup = false;
045 protected boolean useShortLabel = false;
046 protected String defaultValue;
047 protected Class<? extends ValueFinder> defaultValueFinderClass;
048 protected String quickfinderParameterString;
049 protected Class<? extends ValueFinder> quickfinderParameterStringBuilderClass;
050
051 protected Integer maxLength = null;
052
053 protected String displayEditMode;
054 protected Mask displayMask;
055
056 protected boolean hidden = false;
057 protected boolean readOnly = false;
058
059 protected boolean treatWildcardsAndOperatorsAsLiteral = false;
060
061 protected String alternateDisplayAttributeName;
062 protected String additionalDisplayAttributeName;
063
064 protected boolean triggerOnChange;
065 protected boolean total = false;
066
067 public FieldDefinition() {
068 }
069
070
071 /**
072 * @return attributeName
073 */
074 public String getAttributeName() {
075 return attributeName;
076 }
077
078 /**
079 * Sets attributeName to the given value.
080 *
081 * @param attributeName
082 * @throws IllegalArgumentException if the given attributeName is blank
083 */
084 public void setAttributeName(String attributeName) {
085 if (StringUtils.isBlank(attributeName)) {
086 throw new IllegalArgumentException("invalid (blank) attributeName");
087 }
088 this.attributeName = attributeName;
089 }
090
091
092 /**
093 * @return true if this attribute is required
094 */
095 public boolean isRequired() {
096 return required;
097 }
098
099
100 /**
101 required = true means that the user must enter something
102 into the search criterion lookup field
103 */
104 public void setRequired(boolean required) {
105 this.required = required;
106 }
107
108
109 /**
110 * @return Returns the forceInquiry.
111 */
112 public boolean isForceInquiry() {
113 return forceInquiry;
114 }
115
116
117 /**
118 * forceInquiry = true means that the displayed field value will
119 always be made inquirable (this attribute is not used within the code).
120 */
121 public void setForceInquiry(boolean forceInquiry) {
122 this.forceInquiry = forceInquiry;
123 }
124
125 /**
126 * @return Returns the forceLookup.
127 */
128 public boolean isForceLookup() {
129 return forceLookup;
130 }
131
132 /**
133 * forceLookup = this attribute is not used
134 */
135 public void setForceLookup(boolean forceLookup) {
136 this.forceLookup = forceLookup;
137 }
138
139 /**
140 * @return Returns the noInquiry.
141 */
142 public boolean isNoInquiry() {
143 return noInquiry;
144 }
145
146 /**
147 * @return Returns a boolean value indicating whether or not to provide
148 * a direct inquiry for the lookup field
149 */
150 public boolean isNoDirectInquiry()
151 {
152 return noDirectInquiry;
153 }
154
155 /**
156 * noInquiry = true means that the displayed field will never be made inquirable.
157 */
158 public void setNoInquiry(boolean noInquiry) {
159 this.noInquiry = noInquiry;
160 }
161
162 /**
163 * @param noInquiry If true, the displayed field will not have a direct
164 * inquiry facility
165 */
166 public void setNoDirectInquiry(boolean noDirectInquiry) {
167 this.noDirectInquiry = noDirectInquiry;
168 }
169
170 /**
171 * @return Returns the noLookup.
172 */
173 public boolean isNoLookup() {
174 return noLookup;
175 }
176
177 /**
178 * noLookup = true means that field should not include magnifying glass (i.e. quickfinder)
179 */
180 public void setNoLookup(boolean noLookup) {
181 this.noLookup = noLookup;
182 }
183
184
185 /**
186 * @return the useShortLabel
187 */
188 public boolean isUseShortLabel() {
189 return this.useShortLabel;
190 }
191
192
193 /**
194 * @param useShortLabel the useShortLabel to set
195 */
196 public void setUseShortLabel(boolean useShortLabel) {
197 this.useShortLabel = useShortLabel;
198 }
199
200
201 /**
202 * @return Returns the defaultValue.
203 */
204 public String getDefaultValue() {
205 return defaultValue;
206 }
207
208
209 /**
210 The defaultValue element will pre-load the specified value
211 into the field.
212 */
213 public void setDefaultValue(String defaultValue) {
214 this.defaultValue = defaultValue;
215 }
216
217 /**
218 * the quickfinderParameterString is a comma separated list of parameter/value pairs, of the format
219 * "param1=value1,param2=value2", where the parameters correspond to attributes of the target class
220 * for the quickfinder, and the values to literals that those attributes will default to when the
221 * quickfinder is used.
222 * @return the quickfinderParameterString
223 */
224 public String getQuickfinderParameterString() {
225 return this.quickfinderParameterString;
226 }
227
228 /**
229 * @param quickfinderParameterString the quickfinderParameterString to set. See {@link #getQuickfinderParameterString()}
230 */
231 public void setQuickfinderParameterString(String quickfinderParameterString) {
232 this.quickfinderParameterString = quickfinderParameterString;
233 }
234
235
236 /**
237 * the quickfinderParameterStringBuilderClass specifies the java class that will be used
238 * to determine the default value(s) for field(s) on the target lookup when the quickfinder
239 * is used. The classname specified in this field must implement
240 * {@link org.kuali.rice.krad.valuefinder.ValueFinder}. See {@link #getQuickfinderParameterString()}
241 * for the result string format.
242 * @return the quickfinderParameterStringBuilderClass
243 */
244 public Class<? extends ValueFinder> getQuickfinderParameterStringBuilderClass() {
245 return this.quickfinderParameterStringBuilderClass;
246 }
247
248 /**
249 * See {@link #getQuickfinderParameterStringBuilderClass()}
250 * @param quickfinderParameterStringBuilderClass the quickfinderParameterStringBuilderClass to set
251 */
252 public void setQuickfinderParameterStringBuilderClass(
253 Class<? extends ValueFinder> quickfinderParameterStringBuilderClass) {
254 if (quickfinderParameterStringBuilderClass == null) {
255 throw new IllegalArgumentException("invalid (null) quickfinderParameterStringBuilderClass");
256 }
257 this.quickfinderParameterStringBuilderClass = quickfinderParameterStringBuilderClass;
258 }
259
260 /**
261 * Directly validate simple fields.
262 *
263 * @see org.kuali.rice.krad.datadictionary.DataDictionaryDefinition#completeValidation(java.lang.Class, java.lang.Object)
264 */
265 public void completeValidation(Class rootBusinessObjectClass, Class otherBusinessObjectClass) {
266 BusinessObjectMetaDataService boMetadataService = KNSServiceLocator.getBusinessObjectMetaDataService();
267
268 if (!DataDictionary.isPropertyOf(rootBusinessObjectClass, getAttributeName())) {
269 throw new AttributeValidationException("unable to find attribute '" + attributeName + "' in rootBusinessObjectClass '" + rootBusinessObjectClass.getName() + "' (" + "" + ")");
270 }
271
272 if (StringUtils.isNotBlank(getAlternateDisplayAttributeName())) {
273 if (!DataDictionary.isPropertyOf(rootBusinessObjectClass, getAlternateDisplayAttributeName())) {
274 throw new AttributeValidationException("unable to find attribute named '" + getName() + "' in rootBusinessObjectClass '" + rootBusinessObjectClass.getName() + "' (" + "" + ")");
275 }
276 }
277
278 if (StringUtils.isNotBlank(getAdditionalDisplayAttributeName())) {
279 if (!DataDictionary.isPropertyOf(rootBusinessObjectClass, getAdditionalDisplayAttributeName())) {
280 throw new AttributeValidationException("unable to find attribute named '" + getName() + "' in rootBusinessObjectClass '" + rootBusinessObjectClass.getName() + "' (" + "" + ")");
281 }
282 }
283
284 if (defaultValueFinderClass != null && defaultValue != null) {
285 throw new AttributeValidationException("Both defaultValue and defaultValueFinderClass can not be specified on attribute " + getAttributeName() + " in rootBusinessObjectClass " + rootBusinessObjectClass.getName());
286 }
287
288 validateQuickfinderParameters(rootBusinessObjectClass, boMetadataService);
289
290 if (forceInquiry == true && noInquiry == true) {
291 throw new AttributeValidationException("Both forceInquiry and noInquiry can not be set to true on attribute " + getAttributeName() + " in rootBusinessObjectClass " + rootBusinessObjectClass.getName());
292 }
293 if (forceLookup == true && noLookup == true) {
294 throw new AttributeValidationException("Both forceLookup and noLookup can not be set to true on attribute " + getAttributeName() + " in rootBusinessObjectClass " + rootBusinessObjectClass.getName());
295 }
296 }
297
298
299 /**
300 * This method does validation on the quickfinderParameterString and quickfinderParameterStringBuilderClass members
301 *
302 * @param rootBusinessObjectClass
303 * @param boMetadataService
304 */
305 private void validateQuickfinderParameters(Class rootBusinessObjectClass,
306 BusinessObjectMetaDataService boMetadataService) {
307 if (quickfinderParameterStringBuilderClass != null && quickfinderParameterString != null) {
308 throw new AttributeValidationException("Both quickfinderParameterString and quickfinderParameterStringBuilderClass can not be specified on attribute " + getAttributeName() + " in rootBusinessObjectClass " + rootBusinessObjectClass.getName());
309 }
310
311 // String used for building exception messages
312 String quickfinderParameterStringSource = "quickfinderParameterString";
313
314 if (quickfinderParameterStringBuilderClass != null) {
315 try {
316 quickfinderParameterStringSource = "quickfinderParameterStringBuilderClass " + quickfinderParameterStringBuilderClass.getCanonicalName();
317 quickfinderParameterString = quickfinderParameterStringBuilderClass.newInstance().getValue();
318 } catch (InstantiationException e) {
319 throw new ClassValidationException("unable to create new instance of "+ quickfinderParameterStringSource +" while validating rootBusinessObjectClass '"+ rootBusinessObjectClass.getName() +"'", e);
320 } catch (IllegalAccessException e) {
321 throw new ClassValidationException("unable to create new instance of "+ quickfinderParameterStringSource +" while validating rootBusinessObjectClass '"+ rootBusinessObjectClass.getName() +"'", e);
322 }
323 }
324
325 if (!StringUtils.isEmpty(quickfinderParameterString)) {
326 // quickfinderParameterString will look something like "campusTypeCode=P,active=Y"
327 for (String quickfinderParam : quickfinderParameterString.split(",")) { // this is guaranteed to return at least one
328 if (quickfinderParam.contains("=")) {
329 String propertyName = quickfinderParam.split("=")[0];
330 RelationshipDefinition relationship = boMetadataService.getBusinessObjectRelationshipDefinition(rootBusinessObjectClass, attributeName);
331 Class targetClass = relationship.getTargetClass();
332
333 // This is insufficient to ensure the property is valid for a lookup default, but it's better than nothing.
334 if (!DataDictionary.isPropertyOf(targetClass, propertyName)) {
335 throw new ClassValidationException("malformed parameter string '"+ quickfinderParameterString +"' from "+ quickfinderParameterStringSource +
336 ", '"+ propertyName +"' is not a property of "+ targetClass +"' for rootBusinessObjectClass '"+ rootBusinessObjectClass.getName() +"'");
337 }
338
339 } else {
340 throw new ClassValidationException("malformed parameter string '"+ quickfinderParameterString +"' from "+ quickfinderParameterStringSource +
341 " for rootBusinessObjectClass '"+ rootBusinessObjectClass.getName() +"'");
342 }
343 }
344 }
345 }
346
347
348 /**
349 * @see java.lang.Object#toString()
350 */
351 public String toString() {
352 return "FieldDefinition for attribute " + getAttributeName();
353 }
354
355
356 public String getName() {
357 return attributeName;
358 }
359
360
361 public String getDisplayEditMode() {
362 return displayEditMode;
363 }
364
365
366 /*
367 The document authorizer classes have a method getEditMode, which is a map of edit mode to
368 value mappings. Depending on the context, the value of the mapping may be relevant, and the logic determining
369 whether the value is relevant is often implemented in the JSP/tag layer.
370
371 Fields on a document (particularily maintenance documents) may be associated with
372 an edit mode. If the edit mode is mapped to a relevant value, then the all fields associated with the edit mode
373 will be rendered unhidden.
374
375 The displayEditMode element is used to specify the edit mode that will be associated with the field.
376 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.
377 */
378 public void setDisplayEditMode(String displayEditMode) {
379 this.displayEditMode = displayEditMode;
380 }
381
382
383 public Mask getDisplayMask() {
384 return displayMask;
385 }
386
387 /**
388 * The displayMask element specifies the type of masking to
389 be used to hide the value from un-authorized users.
390 There are three types of masking.
391 */
392 public void setDisplayMask(Mask displayMask) {
393 this.displayMask = displayMask;
394 }
395
396
397
398 public boolean isReadOnlyAfterAdd() {
399 return false;
400 }
401
402
403 /**
404 * Gets the maxLength attribute.
405 * @return Returns the maxLength.
406 */
407 public Integer getMaxLength() {
408 return maxLength;
409 }
410
411
412 /**
413 * maxLength = the maximum allowable length of the field in the lookup result fields. In other contexts,
414 like inquiries, this field has no effect.
415 */
416 public void setMaxLength(Integer maxLength) {
417 this.maxLength = maxLength;
418 }
419
420 /**
421 * @return custom defaultValue class
422 */
423 public Class<? extends ValueFinder> getDefaultValueFinderClass() {
424 return this.defaultValueFinderClass;
425 }
426
427 /**
428 The defaultValueFinderClass specifies the java class that will be
429 used to determine the default value of a field. The classname
430 specified in this field must implement ValueFinder
431 */
432 public void setDefaultValueFinderClass(Class<? extends ValueFinder> defaultValueFinderClass) {
433 if (defaultValueFinderClass == null) {
434 throw new IllegalArgumentException("invalid (null) defaultValueFinderClass");
435 }
436 this.defaultValueFinderClass = defaultValueFinderClass;
437 }
438
439 /**
440 * @return the hidden
441 */
442 public boolean isHidden() {
443 return this.hidden;
444 }
445
446 /**
447 * @param hidden
448 * If the ControlDefinition.isHidden == true then a corresponding LookupDefinition would
449 * automatically be removed from the search criteria. In some cases you might want the
450 * hidden field to be used as a search criteria. For example, in PersonImpl.xml a client
451 * might want to have the campus code hidden and preset to Bloomington. So when the search
452 * is run, only people from the bloomington campus are returned.
453 *
454 * So, if you want to have a hidden search criteria, set this variable to true. Defaults to
455 * false.
456 */
457 public void setHidden(boolean hidden) {
458 this.hidden = hidden;
459 }
460
461 /**
462 * @return the readOnly
463 */
464 public boolean isReadOnly() {
465 return this.readOnly;
466 }
467
468 /**
469 * @param readOnly the readOnly to set
470 */
471 public void setReadOnly(boolean readOnly) {
472 this.readOnly = readOnly;
473 }
474
475 public boolean isTriggerOnChange() {
476 return this.triggerOnChange;
477 }
478
479 public void setTriggerOnChange(boolean triggerOnChange) {
480 this.triggerOnChange = triggerOnChange;
481 }
482
483 /**
484 * @return the treatWildcardsAndOperatorsAsLiteralOnLookups
485 */
486 public boolean isTreatWildcardsAndOperatorsAsLiteral() {
487 return this.treatWildcardsAndOperatorsAsLiteral;
488 }
489
490
491 /**
492 * @param treatWildcardsAndOperatorsAsLiteralOnLookups the treatWildcardsAndOperatorsAsLiteralOnLookups to set
493 */
494 public void setTreatWildcardsAndOperatorsAsLiteral(
495 boolean treatWildcardsAndOperatorsAsLiteralOnLookups) {
496 this.treatWildcardsAndOperatorsAsLiteral = treatWildcardsAndOperatorsAsLiteralOnLookups;
497 }
498
499
500 public String getAlternateDisplayAttributeName() {
501 return this.alternateDisplayAttributeName;
502 }
503
504
505 public void setAlternateDisplayAttributeName(String alternateDisplayAttributeName) {
506 this.alternateDisplayAttributeName = alternateDisplayAttributeName;
507 }
508
509
510 public String getAdditionalDisplayAttributeName() {
511 return this.additionalDisplayAttributeName;
512 }
513
514
515 public void setAdditionalDisplayAttributeName(String additionalDisplayAttributeName) {
516 this.additionalDisplayAttributeName = additionalDisplayAttributeName;
517 }
518
519
520 public boolean isTotal() {
521 return this.total;
522 }
523
524
525 public void setTotal(boolean total) {
526 this.total = total;
527 }
528
529 }