1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kim.lookup;
17
18 import static java.util.Collections.sort;
19
20 import java.sql.Date;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Comparator;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.ListIterator;
29 import java.util.Map;
30 import java.util.Properties;
31
32 import org.apache.commons.collections.CollectionUtils;
33 import org.apache.commons.lang.StringUtils;
34 import org.kuali.rice.core.util.ClassLoaderUtils;
35 import org.kuali.rice.core.util.KeyLabelPair;
36 import org.kuali.rice.kew.util.KEWConstants;
37 import org.kuali.rice.kim.bo.Group;
38 import org.kuali.rice.kim.bo.Person;
39 import org.kuali.rice.kim.bo.group.dto.GroupInfo;
40 import org.kuali.rice.kim.bo.impl.GroupImpl;
41 import org.kuali.rice.kim.bo.types.dto.AttributeDefinitionMap;
42 import org.kuali.rice.kim.bo.types.dto.KimTypeInfo;
43 import org.kuali.rice.kim.bo.ui.KimAttributeDataComparator;
44 import org.kuali.rice.kim.dao.KimGroupDao;
45 import org.kuali.rice.kim.service.KIMServiceLocator;
46 import org.kuali.rice.kim.service.support.KimTypeService;
47 import org.kuali.rice.kim.util.KIMPropertyConstants;
48 import org.kuali.rice.kim.util.KimCommonUtils;
49 import org.kuali.rice.kim.util.KimConstants;
50 import org.kuali.rice.kns.authorization.BusinessObjectRestrictions;
51 import org.kuali.rice.kns.bo.BusinessObject;
52 import org.kuali.rice.kns.bo.PersistableBusinessObject;
53 import org.kuali.rice.kns.datadictionary.AttributeDefinition;
54 import org.kuali.rice.kns.datadictionary.KimDataDictionaryAttributeDefinition;
55 import org.kuali.rice.kns.datadictionary.KimNonDataDictionaryAttributeDefinition;
56 import org.kuali.rice.kns.lookup.HtmlData;
57 import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
58 import org.kuali.rice.kns.lookup.keyvalues.IndicatorValuesFinder;
59 import org.kuali.rice.kns.lookup.keyvalues.KeyValuesFinder;
60 import org.kuali.rice.kns.lookup.keyvalues.KimAttributeValuesFinder;
61 import org.kuali.rice.kns.util.GlobalVariables;
62 import org.kuali.rice.kns.util.KNSConstants;
63 import org.kuali.rice.kns.util.ObjectUtils;
64 import org.kuali.rice.kns.util.UrlFactory;
65 import org.kuali.rice.kns.web.comparator.CellComparatorHelper;
66 import org.kuali.rice.kns.web.format.BooleanFormatter;
67 import org.kuali.rice.kns.web.format.CollectionFormatter;
68 import org.kuali.rice.kns.web.format.DateFormatter;
69 import org.kuali.rice.kns.web.format.Formatter;
70 import org.kuali.rice.kns.web.struts.form.LookupForm;
71 import org.kuali.rice.kns.web.ui.Column;
72 import org.kuali.rice.kns.web.ui.Field;
73 import org.kuali.rice.kns.web.ui.ResultRow;
74 import org.kuali.rice.kns.web.ui.Row;
75
76
77
78
79
80
81
82 public class GroupLookupableHelperServiceImpl extends KimLookupableHelperServiceImpl {
83
84
85
86
87 private static String KIM_TYPE_ID_PROPERTY_NAME = "kimTypeId";
88 private List<Row> grpRows = new ArrayList<Row>();
89 private List<Row> attrRows = new ArrayList<Row>();
90 private KimGroupDao groupDao;
91 private String typeId = "";
92 private AttributeDefinitionMap attrDefinitions;
93 private Map<String, String> groupTypeValuesCache = new HashMap<String, String>();
94
95 @Override
96 public List<HtmlData> getCustomActionUrls(BusinessObject bo, List pkNames) {
97 GroupImpl groupImpl = (GroupImpl) bo;
98 List<HtmlData> anchorHtmlDataList = new ArrayList<HtmlData>();
99 if(allowsNewOrCopyAction(KimConstants.KimUIConstants.KIM_GROUP_DOCUMENT_TYPE_NAME)){
100 anchorHtmlDataList.add(getEditGroupUrl(groupImpl));
101 }
102 return anchorHtmlDataList;
103 }
104
105 protected HtmlData getEditGroupUrl(GroupImpl groupImpl) {
106 String href = "";
107
108 Properties parameters = new Properties();
109 parameters.put(KNSConstants.DISPATCH_REQUEST_PARAMETER, KNSConstants.DOC_HANDLER_METHOD);
110 parameters.put(KNSConstants.PARAMETER_COMMAND, KEWConstants.INITIATE_COMMAND);
111 parameters.put(KNSConstants.DOCUMENT_TYPE_NAME, KimConstants.KimUIConstants.KIM_GROUP_DOCUMENT_TYPE_NAME);
112 parameters.put(KimConstants.PrimaryKeyConstants.GROUP_ID, groupImpl.getGroupId());
113 if (StringUtils.isNotBlank(getReturnLocation())) {
114 parameters.put(KNSConstants.RETURN_LOCATION_PARAMETER, getReturnLocation());
115 }
116 href = UrlFactory.parameterizeUrl(KimCommonUtils.getKimBasePath()+KimConstants.KimUIConstants.KIM_GROUP_DOCUMENT_ACTION, parameters);
117
118 AnchorHtmlData anchorHtmlData = new AnchorHtmlData(href,
119 KNSConstants.DOC_HANDLER_METHOD, KNSConstants.MAINTENANCE_EDIT_METHOD_TO_CALL);
120 return anchorHtmlData;
121 }
122
123
124
125
126
127
128
129
130 @Override
131 public List<GroupImpl> getSearchResults(java.util.Map<String,String> fieldValues) {
132 List<? extends Group> groupInfoObjs = KIMServiceLocator.getGroupService().lookupGroups(fieldValues);
133 List<GroupImpl> groupImplList = new ArrayList<GroupImpl>();
134 for(Group g : groupInfoObjs){
135 GroupImpl impl = new GroupImpl();
136 impl = KimCommonUtils.copyInfoToGroup(g, impl);
137 impl.setGroupAttributes(KimCommonUtils.copyInfoAttributesToGroupAttributes(g.getAttributes(), g.getGroupId(), g.getKimTypeId()));
138 groupImplList.add(impl);
139 }
140 return groupImplList;
141 }
142
143 @Override
144 public boolean checkForAdditionalFields(Map fieldValues) {
145 List<Row> attributeRows = setupAttributeRows(fieldValues);
146 if (attributeRows.isEmpty()) {
147 setAttrRows(attributeRows);
148 } else if (CollectionUtils.isEmpty(getAttrRows())) {
149 setAttrRows(attributeRows);
150 }
151 if (getAttrRows().size() > 0) {
152 return true;
153 }
154 return false;
155 }
156
157
158 @Override
159 public List<Row> getRows() {
160 if (getGrpRows().isEmpty()) {
161 List<Row> rows = super.getRows();
162 List<Row> returnRows = new ArrayList<Row>();
163 for (Row row : rows) {
164 for (int i = row.getFields().size() - 1; i >= 0; i--) {
165 Field field = row.getFields().get(i);
166 if (field.getPropertyName().equals(KIM_TYPE_ID_PROPERTY_NAME)) {
167 Field typeField = new Field();
168 typeField.setFieldLabel("Type");
169 typeField.setPropertyName(KIM_TYPE_ID_PROPERTY_NAME);
170 typeField.setFieldValidValues(getGroupTypeOptions());
171 typeField.setFieldType(Field.DROPDOWN);
172 row.getFields().set(i, typeField);
173 }
174 }
175 returnRows.add(row);
176 }
177
178 Field typeField = new Field();
179 typeField.setFieldLabel("Principal Name");
180 typeField.setPropertyName(KIMPropertyConstants.Person.PRINCIPAL_NAME);
181 typeField.setFieldType(Field.TEXT);
182 typeField.setMaxLength(40);
183 typeField.setSize(20);
184 typeField.setQuickFinderClassNameImpl("org.kuali.rice.kim.bo.Person");
185 typeField.setFieldConversions( "principalName:principalName" );
186 typeField.setLookupParameters( "principalName:principalName" );
187
188
189
190 List<Field> fields = (returnRows.isEmpty()) ? new ArrayList<Field>() : returnRows.get(returnRows.size() - 1).getFields();
191 if (!fields.isEmpty() && fields.get(fields.size() - 1).getFieldType().equals(Field.BLANK_SPACE)) {
192
193 int insertLoc = fields.size() - 1;
194 while (insertLoc >= 0 && fields.get(insertLoc).getFieldType().equals(Field.BLANK_SPACE)) {
195 insertLoc--;
196 }
197 fields.set(insertLoc + 1, typeField);
198 returnRows.get(returnRows.size() - 1).setFields(fields);
199 } else {
200
201 int fieldLen = fields.size();
202 fields = new ArrayList<Field>();
203 fields.add(typeField);
204 for (int i = 1; i < fieldLen; i++) {
205 Field blankSpace = new Field();
206 blankSpace.setFieldType(Field.BLANK_SPACE);
207 blankSpace.setPropertyName(Field.BLANK_SPACE);
208 fields.add(blankSpace);
209 }
210 returnRows.add(new Row(fields));
211 }
212
213 setGrpRows(returnRows);
214 }
215 if (getAttrRows().isEmpty()) {
216 setAttrDefinitions(new AttributeDefinitionMap());
217 return getGrpRows();
218 } else {
219 List<Row> fullRows = new ArrayList<Row>();
220 fullRows.addAll(getGrpRows());
221 fullRows.addAll(getAttrRows());
222 return fullRows;
223 }
224
225 }
226
227
228 @Override
229 public List<Column> getColumns() {
230 List<Column> columns = super.getColumns();
231 for (Row row : attrRows) {
232 for (Field field : row.getFields()) {
233 Column newColumn = new Column();
234 newColumn.setColumnTitle(field.getFieldLabel());
235 newColumn.setMaxLength(getColumnMaxLength(field.getPropertyName()));
236 newColumn.setPropertyName(field.getPropertyName());
237 newColumn.setFormatter((Formatter) field.getFormatter());
238 columns.add(newColumn);
239 }
240 }
241 return columns;
242 }
243
244 public Collection performLookup(LookupForm lookupForm, Collection resultTable, boolean bounded) {
245 setBackLocation((String) lookupForm.getFieldsForLookup().get(KNSConstants.BACK_LOCATION));
246 setDocFormKey((String) lookupForm.getFieldsForLookup().get(KNSConstants.DOC_FORM_KEY));
247 Collection displayList;
248
249
250 if (bounded) {
251 displayList = getSearchResults(lookupForm.getFieldsForLookup());
252 }
253 else {
254 displayList = getSearchResultsUnbounded(lookupForm.getFieldsForLookup());
255 }
256
257 HashMap<String,Class> propertyTypes = new HashMap<String, Class>();
258
259 boolean hasReturnableRow = false;
260
261 List returnKeys = getReturnKeys();
262 List pkNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(getBusinessObjectClass());
263 Person user = GlobalVariables.getUserSession().getPerson();
264
265
266 for (Iterator iter = displayList.iterator(); iter.hasNext();) {
267 BusinessObject element = (BusinessObject) iter.next();
268 if(element instanceof PersistableBusinessObject){
269 lookupForm.setLookupObjectId(((PersistableBusinessObject)element).getObjectId());
270 }
271
272 BusinessObjectRestrictions businessObjectRestrictions = getBusinessObjectAuthorizationService().getLookupResultRestrictions(element, user);
273
274 HtmlData returnUrl = getReturnUrl(element, lookupForm, returnKeys, businessObjectRestrictions);
275
276 String actionUrls = getActionUrls(element, pkNames, businessObjectRestrictions);
277
278 if("".equals(actionUrls)){
279 actionUrls = ACTION_URLS_EMPTY;
280 }
281
282 List<Column> columns = getColumns();
283 for (Iterator iterator = columns.iterator(); iterator.hasNext();) {
284
285 Column col = (Column) iterator.next();
286 Formatter formatter = col.getFormatter();
287
288
289 String propValue = KNSConstants.EMPTY_STRING;
290 Object prop = null;
291 boolean skipPropTypeCheck = false;
292 if (col.getPropertyName().matches("\\w+\\.\\d+$")) {
293 String id = col.getPropertyName().substring(col.getPropertyName().lastIndexOf('.') + 1);
294 prop = ((GroupImpl)element).getGroupAttributeValueById(id);
295 }
296 if (prop == null) {
297 prop = ObjectUtils.getPropertyValue(element, col.getPropertyName());
298 } else {
299 skipPropTypeCheck = true;
300 }
301
302
303 Class propClass = propertyTypes.get(col.getPropertyName());
304 if ( propClass == null
305 try {
306 propClass = ObjectUtils.getPropertyType( element, col.getPropertyName(), getPersistenceStructureService() );
307 propertyTypes.put( col.getPropertyName(), propClass );
308 } catch (Exception e) {
309 throw new RuntimeException("Cannot access PropertyType for property " + "'" + col.getPropertyName() + "' " + " on an instance of '" + element.getClass().getName() + "'.", e);
310 }
311 }
312
313
314 if (prop != null) {
315
316 if (prop instanceof Boolean) {
317 formatter = new BooleanFormatter();
318 }
319
320
321 if (prop instanceof Date) {
322 formatter = new DateFormatter();
323 }
324
325
326 if (prop instanceof Collection && formatter == null) {
327 formatter = new CollectionFormatter();
328 }
329
330 if (formatter != null) {
331 propValue = (String) formatter.format(prop);
332 }
333 else {
334 propValue = prop.toString();
335 if (col.getPropertyName().equals(KIM_TYPE_ID_PROPERTY_NAME)) {
336 propValue = groupTypeValuesCache.get(prop.toString());
337 }
338 }
339 }
340
341
342 col.setComparator(CellComparatorHelper.getAppropriateComparatorForPropertyClass(propClass));
343 col.setValueComparator(CellComparatorHelper.getAppropriateValueComparatorForPropertyClass(propClass));
344
345 propValue = maskValueIfNecessary(element.getClass(), col.getPropertyName(), propValue, businessObjectRestrictions);
346
347 col.setPropertyValue(propValue);
348
349 if (StringUtils.isNotBlank(propValue)) {
350 col.setColumnAnchor(getInquiryUrl(element, col.getPropertyName()));
351
352 }
353 }
354
355 ResultRow row = new ResultRow(columns, returnUrl.constructCompleteHtmlTag(), actionUrls);
356 row.setRowId(returnUrl.getName());
357 row.setReturnUrlHtmlData(returnUrl);
358
359
360 if (getBusinessObjectDictionaryService().isExportable(getBusinessObjectClass())) {
361 row.setBusinessObject(element);
362 }
363 if(element instanceof PersistableBusinessObject){
364 row.setObjectId((((PersistableBusinessObject)element).getObjectId()));
365 }
366
367
368 boolean rowReturnable = isResultReturnable(element);
369 row.setRowReturnable(rowReturnable);
370 if (rowReturnable) {
371 hasReturnableRow = true;
372 }
373 resultTable.add(row);
374 }
375
376 lookupForm.setHasReturnableRow(hasReturnableRow);
377
378 return displayList;
379 }
380
381 private List<KeyLabelPair> getGroupTypeOptions() {
382 List<KeyLabelPair> options = new ArrayList<KeyLabelPair>();
383 options.add(new KeyLabelPair("", ""));
384
385 Collection<KimTypeInfo> kimGroupTypes = KIMServiceLocator.getTypeInfoService().getAllTypes();
386
387 for (KimTypeInfo kimType : kimGroupTypes) {
388 if (KimTypeLookupableHelperServiceImpl.hasGroupTypeService(kimType) && groupTypeValuesCache.get(kimType.getKimTypeId()) == null) {
389 String value = kimType.getNamespaceCode().trim() + KNSConstants.FIELD_CONVERSION_PAIR_SEPARATOR + kimType.getName().trim();
390 options.add(new KeyLabelPair(kimType.getKimTypeId(), value));
391 }
392 }
393 Collections.sort(options, new Comparator<KeyLabelPair>() {
394 public int compare(KeyLabelPair k1, KeyLabelPair k2) {
395 return k1.getLabel().compareTo(k2.getLabel());
396 }
397 });
398 return options;
399 }
400
401 private List<Row> setupAttributeRows(Map fieldValues) {
402 List<Row> returnRows = new ArrayList<Row>();
403 for (Row row : getGrpRows()) {
404 Field field = (Field) row.getFields().get(0);
405 if (field.getPropertyName().equals(KIM_TYPE_ID_PROPERTY_NAME) && StringUtils.isNotBlank(field.getPropertyValue())) {
406 if (!StringUtils.isBlank(getTypeId()) || !getTypeId().equals(field.getPropertyValue())) {
407 setTypeId(field.getPropertyValue());
408 setAttrRows(new ArrayList<Row>());
409 KimTypeInfo kimType = getTypeInfoService().getKimType( field.getPropertyValue() );
410 KimTypeService kimTypeService = KimCommonUtils.getKimTypeService(kimType);
411 AttributeDefinitionMap definitions = kimTypeService.getAttributeDefinitions(kimType.getKimTypeId());
412 setAttrDefinitions(definitions);
413 for (AttributeDefinition definition : definitions.values()) {
414 List<Field> fields = new ArrayList<Field>();
415 Field typeField = new Field();
416
417 String attrDefnId = getAttrDefnId(definition);
418 typeField.setFieldLabel(definition.getLabel());
419 typeField.setPropertyName(definition.getName()+"."+attrDefnId);
420 typeField.setPropertyValue(fieldValues.get(typeField.getPropertyName()));
421 if (definition.getControl().isSelect()) {
422 try {
423 KeyValuesFinder finder = (KeyValuesFinder) ClassLoaderUtils.getClass(definition.getControl().getValuesFinderClass()).newInstance();
424
425 if (finder instanceof KimAttributeValuesFinder) {
426 ((KimAttributeValuesFinder) finder).setKimTypeId(field.getPropertyValue());
427 ((KimAttributeValuesFinder) finder).setKimAttributeName(definition.getName());
428 }
429 typeField.setFieldValidValues(finder.getKeyValues());
430 typeField.setFieldType(Field.DROPDOWN);
431 }
432 catch (InstantiationException e) {
433 throw new RuntimeException(e.getMessage());
434 }
435 catch (IllegalAccessException e) {
436 throw new RuntimeException(e.getMessage());
437 }
438 } else if (definition.getControl().isText()){
439 typeField.setMaxLength(definition.getMaxLength());
440 if (definition.getControl().getSize() != null) {
441 typeField.setSize(definition.getControl().getSize());
442 }
443 typeField.setFieldType(Field.TEXT);
444 } else if (definition.getControl().isRadio()) {
445 try {
446 KeyValuesFinder finder = (KeyValuesFinder) ClassLoaderUtils.getClass(definition.getControl().getValuesFinderClass()).newInstance();
447 typeField.setFieldValidValues(finder.getKeyValues());
448 typeField.setFieldType(Field.RADIO);
449 }
450 catch (InstantiationException e) {
451 throw new RuntimeException(e.getMessage());
452 }
453 catch (IllegalAccessException e) {
454 throw new RuntimeException(e.getMessage());
455 }
456 } else if (definition.getControl().isCheckbox()) {
457 KeyValuesFinder finder = (KeyValuesFinder)new IndicatorValuesFinder();
458 typeField.setFieldValidValues(finder.getKeyValues());
459 typeField.setFieldType(Field.RADIO);
460
461 } else if (definition.getControl().isHidden()) {
462 typeField.setFieldType(Field.HIDDEN);
463 } else if (definition.getControl().isLookupReadonly()) {
464 typeField.setFieldType(Field.LOOKUP_READONLY);
465 } else if (definition.getControl().isTextarea()) {
466 typeField.setMaxLength(definition.getMaxLength());
467 if (definition.getControl().getSize() != null) {
468 typeField.setSize(definition.getControl().getSize());
469 }
470 typeField.setFieldType(Field.TEXT_AREA);
471 }
472 fields.add(typeField);
473 returnRows.add(new Row(fields));
474 }
475 } else {
476 return getAttrRows();
477 }
478 } else if (field.getPropertyName().equals(KIM_TYPE_ID_PROPERTY_NAME) && StringUtils.isBlank(field.getPropertyValue())) {
479 setTypeId("");
480 }
481 }
482 return returnRows;
483 }
484
485 private String getAttrDefnId(AttributeDefinition definition) {
486 if (definition instanceof KimDataDictionaryAttributeDefinition) {
487 return ((KimDataDictionaryAttributeDefinition)definition).getKimAttrDefnId();
488 } else {
489 return ((KimNonDataDictionaryAttributeDefinition)definition).getKimAttrDefnId();
490
491 }
492 }
493
494 public List<Row> getGrpRows() {
495 return this.grpRows;
496 }
497
498 public void setGrpRows(List<Row> grpRows) {
499 this.grpRows = grpRows;
500 }
501
502 public KimGroupDao getGroupDao() {
503 return this.groupDao;
504 }
505
506 public void setGroupDao(KimGroupDao groupDao) {
507 this.groupDao = groupDao;
508 }
509
510 public AttributeDefinitionMap getAttrDefinitions() {
511 return this.attrDefinitions;
512 }
513
514 public void setAttrDefinitions(AttributeDefinitionMap attrDefinitions) {
515 this.attrDefinitions = attrDefinitions;
516 }
517
518 public List<Row> getAttrRows() {
519 return this.attrRows;
520 }
521
522 public void setAttrRows(List<Row> attrRows) {
523 this.attrRows = attrRows;
524 }
525
526 public String getTypeId() {
527 return this.typeId;
528 }
529
530 public void setTypeId(String typeId) {
531 this.typeId = typeId;
532 }
533
534 @Override
535 public void performClear(LookupForm lookupForm) {
536 super.performClear(lookupForm);
537 this.attrRows = new ArrayList<Row>();
538 }
539
540 }