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