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