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.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.api.KewApiConstants;
30 import org.kuali.rice.kim.api.KimConstants;
31 import org.kuali.rice.kim.api.group.Group;
32 import org.kuali.rice.kim.api.group.GroupQueryResults;
33 import org.kuali.rice.kim.api.identity.Person;
34 import org.kuali.rice.kim.api.identity.principal.Principal;
35 import org.kuali.rice.kim.api.identity.principal.PrincipalQueryResults;
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.data.KradDataServiceLocator;
57 import org.kuali.rice.krad.datadictionary.AttributeDefinition;
58 import org.kuali.rice.krad.keyvalues.IndicatorValuesFinder;
59 import org.kuali.rice.krad.keyvalues.KeyValuesFinder;
60 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
61 import org.kuali.rice.krad.util.GlobalVariables;
62 import org.kuali.rice.krad.util.KRADConstants;
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 String refToRef = criteriaMap.get(KRADConstants.REFERENCES_TO_REFRESH);
134 if (StringUtils.isNotBlank(refToRef) && refToRef.equalsIgnoreCase("GroupBo")) {
135 criteriaMap.remove(KRADConstants.REFERENCES_TO_REFRESH);
136 }
137 boolean validPrncplFoundIfPrncplCritPresent = true;
138 Map<String, String> attribsMap = new HashMap<String, String>();
139 if (!criteriaMap.isEmpty()) {
140 List<Predicate> predicates = new ArrayList<Predicate>();
141
142 if (StringUtils.isNotBlank(criteriaMap.get(KimConstants.UniqueKeyConstants.PRINCIPAL_NAME))) {
143 QueryByCriteria.Builder principalCriteria = QueryByCriteria.Builder.create();
144 Predicate principalPred = like("principalName", criteriaMap.get(KimConstants.UniqueKeyConstants.PRINCIPAL_NAME));
145 principalCriteria.setPredicates(principalPred);
146
147
148 PrincipalQueryResults principals = KimApiServiceLocator.getIdentityService()
149 .findPrincipals(principalCriteria.build());
150 List<String> principalIds = new ArrayList<String>();
151 for (Principal principal : principals.getResults()) {
152 principalIds.add(principal.getPrincipalId());
153 }
154 if (CollectionUtils.isNotEmpty(principalIds)) {
155 Timestamp currentTime = new Timestamp(Calendar.getInstance().getTimeInMillis());
156 predicates.add( and(
157 in("members.memberId", principalIds.toArray(
158 new String[principalIds.size()])),
159 equal("members.typeCode", KimConstants.KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE.getCode()),
160 and(
161 or(isNull("members.activeFromDateValue"), lessThanOrEqual("members.activeFromDateValue", currentTime)),
162 or(isNull("members.activeToDateValue"), greaterThan("members.activeToDateValue", currentTime))
163 )
164 ));
165 }else {
166 validPrncplFoundIfPrncplCritPresent = false;
167 }
168
169 }
170 criteriaMap.remove(KimConstants.UniqueKeyConstants.PRINCIPAL_NAME);
171 Map<String, String> criteriaCopy = new HashMap<String, String>();
172
173 criteriaCopy.putAll(criteriaMap);
174
175 for(String key : criteriaCopy.keySet()) {
176 if (isParamAttribute(key)) {
177 if (StringUtils.isNotBlank(criteriaMap.get(key))) {
178 String attributeName = StringUtils.substringBetween(key, "attributes(", ")");
179 attribsMap.put(attributeName, criteriaMap.get(key));
180 }
181
182
183 criteriaMap.remove(key);
184 }
185 }
186 predicates.add(PredicateUtils.convertMapToPredicate(criteriaMap));
187 criteria.setPredicates(and(predicates.toArray(new Predicate[predicates.size()])));
188 }
189 List<Group> groups = new ArrayList<Group>();
190 if (validPrncplFoundIfPrncplCritPresent) {
191 GroupQueryResults groupResults = KimApiServiceLocator.getGroupService().findGroups(criteria.build());
192 groups = groupResults.getResults();
193 }
194
195
196 Map<String, GroupBo> groupBos = new HashMap<String, GroupBo>(groups.size());
197 for (Group group : groups) {
198
199 if (attribsMap.isEmpty()) {
200 if (groupBos.get(group.getId()) == null) {
201 groupBos.put(group.getId(), GroupBo.from(group));
202 }
203 } else {
204 boolean containsAllAttribs = true;
205 for (String attribute : attribsMap.keySet()) {
206 containsAllAttribs &= group.getAttributes().containsKey(attribute) &&
207 group.getAttributes().get(attribute).equalsIgnoreCase(attribsMap.get(attribute));
208 }
209 if (containsAllAttribs) {
210 if (groupBos.get(group.getId()) == null) {
211 groupBos.put(group.getId(), GroupBo.from(group));
212 }
213 }
214 }
215 }
216
217 return new ArrayList<GroupBo>(groupBos.values());
218 }
219
220
221
222
223
224
225
226
227 private boolean isParamAttribute(String param) {
228 return param.matches("attributes\\((.*?)\\)") &&
229 StringUtils.isNotBlank(StringUtils.substringBetween(param, "attributes(",")")) &&
230 StringUtils.substringBetween(param, "attributes(",")") != "null";
231 }
232
233 @Override
234 public boolean checkForAdditionalFields(Map<String, String> fieldValues) {
235 List<Row> attributeRows = setupAttributeRows(fieldValues);
236 if (attributeRows.isEmpty()) {
237 setAttrRows(attributeRows);
238 } else if (CollectionUtils.isEmpty(getAttrRows())) {
239 setAttrRows(attributeRows);
240 }
241 if (getAttrRows().size() > 0) {
242 return true;
243 }
244 return false;
245 }
246
247
248 @Override
249 public List<Row> getRows() {
250 if (getGrpRows().isEmpty()) {
251 List<Row> rows = super.getRows();
252 List<Row> returnRows = new ArrayList<Row>();
253 for (Row row : rows) {
254 for (int i = row.getFields().size() - 1; i >= 0; i--) {
255 Field field = row.getFields().get(i);
256 if (field.getPropertyName().equals(KIM_TYPE_ID_PROPERTY_NAME)) {
257 Field typeField = new Field();
258 typeField.setFieldLabel("Type");
259 typeField.setPropertyName(KIM_TYPE_ID_PROPERTY_NAME);
260 typeField.setFieldValidValues(getGroupTypeOptions());
261 typeField.setFieldType(Field.DROPDOWN);
262 row.getFields().set(i, typeField);
263 }
264 }
265 returnRows.add(row);
266 }
267
268 Field typeField = new Field();
269 typeField.setFieldLabel("Principal Name");
270 typeField.setPropertyName(KIMPropertyConstants.Person.PRINCIPAL_NAME);
271 typeField.setFieldType(Field.TEXT);
272 typeField.setMaxLength(40);
273 typeField.setSize(20);
274 typeField.setQuickFinderClassNameImpl("org.kuali.rice.kim.api.identity.Person");
275 typeField.setFieldConversions( "principalName:principalName" );
276 typeField.setLookupParameters( "principalName:principalName" );
277
278
279
280 List<Field> fields = (returnRows.isEmpty()) ? new ArrayList<Field>() : returnRows.get(returnRows.size() - 1).getFields();
281 if (!fields.isEmpty() && fields.get(fields.size() - 1).getFieldType().equals(Field.BLANK_SPACE)) {
282
283 int insertLoc = fields.size() - 1;
284 while (insertLoc >= 0 && fields.get(insertLoc).getFieldType().equals(Field.BLANK_SPACE)) {
285 insertLoc--;
286 }
287 fields.set(insertLoc + 1, typeField);
288 returnRows.get(returnRows.size() - 1).setFields(fields);
289 } else {
290
291 int fieldLen = fields.size();
292 fields = new ArrayList<Field>();
293 fields.add(typeField);
294 for (int i = 1; i < fieldLen; i++) {
295 Field blankSpace = new Field();
296 blankSpace.setFieldType(Field.BLANK_SPACE);
297 blankSpace.setPropertyName(Field.BLANK_SPACE);
298 fields.add(blankSpace);
299 }
300 returnRows.add(new Row(fields));
301 }
302
303 setGrpRows(returnRows);
304 }
305 if (getAttrRows().isEmpty()) {
306 setAttrDefinitions(Collections.<KimAttributeField>emptyList());
307 return getGrpRows();
308 }
309 List<Row> fullRows = new ArrayList<Row>();
310 fullRows.addAll(getGrpRows());
311 fullRows.addAll(getAttrRows());
312 return fullRows;
313 }
314
315
316 @Override
317 public List<Column> getColumns() {
318 List<Column> columns = super.getColumns();
319 for (Row row : attrRows) {
320 for (Field field : row.getFields()) {
321 Column newColumn = new Column();
322 newColumn.setColumnTitle(field.getFieldLabel());
323 newColumn.setMaxLength(getColumnMaxLength(field.getPropertyName()));
324 newColumn.setPropertyName(field.getPropertyName());
325 newColumn.setFormatter(field.getFormatter());
326 columns.add(newColumn);
327 }
328 }
329 return columns;
330 }
331
332 @Override
333 public Collection<GroupBo> performLookup(LookupForm lookupForm, Collection resultTable, boolean bounded) {
334 setBackLocation((String) lookupForm.getFieldsForLookup().get(KRADConstants.BACK_LOCATION));
335 setDocFormKey((String) lookupForm.getFieldsForLookup().get(KRADConstants.DOC_FORM_KEY));
336 List<GroupBo> displayList;
337
338
339 if (bounded) {
340 displayList = getSearchResults(lookupForm.getFieldsForLookup());
341 }
342 else {
343 displayList = (List<GroupBo>)getSearchResultsUnbounded(lookupForm.getFieldsForLookup());
344 }
345
346 HashMap<String,Class> propertyTypes = new HashMap<String, Class>();
347
348 boolean hasReturnableRow = false;
349
350 List returnKeys = getReturnKeys();
351 List pkNames = KRADServiceLocatorWeb.getLegacyDataAdapter().listPrimaryKeyFieldNames(getBusinessObjectClass());
352 Person user = GlobalVariables.getUserSession().getPerson();
353
354
355 for (Iterator iter = displayList.iterator(); iter.hasNext();) {
356 BusinessObject element = (BusinessObject) iter.next();
357 if(element instanceof PersistableBusinessObject){
358 lookupForm.setLookupObjectId(((PersistableBusinessObject)element).getObjectId());
359 }
360
361 BusinessObjectRestrictions businessObjectRestrictions = getBusinessObjectAuthorizationService().getLookupResultRestrictions(element, user);
362
363 HtmlData returnUrl = getReturnUrl(element, lookupForm, returnKeys, businessObjectRestrictions);
364
365 String actionUrls = getActionUrls(element, pkNames, businessObjectRestrictions);
366
367 if("".equals(actionUrls)){
368 actionUrls = ACTION_URLS_EMPTY;
369 }
370
371 List<Column> columns = getColumns();
372 for (Object element2 : columns) {
373
374 Column col = (Column) element2;
375 Formatter formatter = col.getFormatter();
376
377
378 String propValue = KRADConstants.EMPTY_STRING;
379 Object prop = null;
380 if (col.getPropertyName().matches("\\w+\\.\\d+$")) {
381 String id = col.getPropertyName().substring(col.getPropertyName().lastIndexOf('.') + 1);
382 prop = ((GroupBo)element).getGroupAttributeValueById(id);
383 }
384 if (prop == null) {
385 prop = (String) KradDataServiceLocator.getDataObjectService().wrap(element)
386 .getPropertyValueNullSafe(findAndConvertAttributeNamesToMappableProperty(col.getPropertyName()));
387 } else {
388 }
389
390
391 Class propClass = propertyTypes.get(col.getPropertyName());
392 if ( propClass == null ) {
393 try {
394 propClass = KRADServiceLocatorWeb.getLegacyDataAdapter().getPropertyType(element,
395 col.getPropertyName());
396 propertyTypes.put( col.getPropertyName(), propClass );
397 } catch (Exception e) {
398 throw new RuntimeException("Cannot access PropertyType for property " + "'" + col.getPropertyName() + "' " + " on an instance of '" + element.getClass().getName() + "'.", e);
399 }
400 }
401
402
403 if (prop != null) {
404
405 if (prop instanceof Boolean) {
406 formatter = new BooleanFormatter();
407 }
408
409
410 if (prop instanceof Date) {
411 formatter = new DateFormatter();
412 }
413
414
415 if (prop instanceof Collection && formatter == null) {
416 formatter = new CollectionFormatter();
417 }
418
419 if (formatter != null) {
420 propValue = (String) formatter.format(prop);
421 }
422 else {
423 propValue = prop.toString();
424 if (col.getPropertyName().equals(KIM_TYPE_ID_PROPERTY_NAME)) {
425 propValue = groupTypeValuesCache.get(prop.toString());
426 }
427 }
428 }
429
430
431 col.setComparator(CellComparatorHelper.getAppropriateComparatorForPropertyClass(propClass));
432 col.setValueComparator(CellComparatorHelper.getAppropriateValueComparatorForPropertyClass(propClass));
433
434 propValue = maskValueIfNecessary(element.getClass(), col.getPropertyName(), propValue, businessObjectRestrictions);
435
436 col.setPropertyValue(propValue);
437
438 if (StringUtils.isNotBlank(propValue)) {
439 col.setColumnAnchor(getInquiryUrl(element, col.getPropertyName()));
440
441 }
442 }
443
444 ResultRow row = new ResultRow(columns, returnUrl.constructCompleteHtmlTag(), actionUrls);
445 row.setRowId(returnUrl.getName());
446 row.setReturnUrlHtmlData(returnUrl);
447
448
449 if (getBusinessObjectDictionaryService().isExportable(getBusinessObjectClass())) {
450 row.setBusinessObject(element);
451 }
452 if(element instanceof PersistableBusinessObject){
453 row.setObjectId((((PersistableBusinessObject)element).getObjectId()));
454 }
455
456
457 boolean rowReturnable = isResultReturnable(element);
458 row.setRowReturnable(rowReturnable);
459 if (rowReturnable) {
460 hasReturnableRow = true;
461 }
462 resultTable.add(row);
463 }
464
465 lookupForm.setHasReturnableRow(hasReturnableRow);
466
467 return displayList;
468 }
469
470
471 private List<KeyValue> getGroupTypeOptions() {
472 List<KeyValue> options = new ArrayList<KeyValue>();
473 options.add(new ConcreteKeyValue("", ""));
474
475 Collection<KimType> kimGroupTypes = KimApiServiceLocator.getKimTypeInfoService().findAllKimTypes();
476
477 for (KimType kimType : kimGroupTypes) {
478 if (KimTypeLookupableHelperServiceImpl.hasGroupTypeService(kimType) && groupTypeValuesCache.get(kimType.getId()) == null) {
479 String value = kimType.getNamespaceCode().trim() + KRADConstants.FIELD_CONVERSION_PAIR_SEPARATOR + kimType.getName().trim();
480 options.add(new ConcreteKeyValue(kimType.getId(), value));
481 }
482 }
483 Collections.sort(options, new Comparator<KeyValue>() {
484 @Override
485 public int compare(KeyValue k1, KeyValue k2) {
486 return k1.getValue().compareTo(k2.getValue());
487 }
488 });
489 return options;
490 }
491
492 private List<Row> setupAttributeRows(Map fieldValues) {
493 List<Row> returnRows = new ArrayList<Row>();
494 for (Row row : getGrpRows()) {
495 Field field = row.getFields().get(0);
496 if (field.getPropertyName().equals(KIM_TYPE_ID_PROPERTY_NAME) && StringUtils.isNotBlank(field.getPropertyValue())) {
497 if (!StringUtils.isBlank(getTypeId()) || !getTypeId().equals(field.getPropertyValue())) {
498 setTypeId(field.getPropertyValue());
499 setAttrRows(new ArrayList<Row>());
500 KimType kimType = getTypeInfoService().getKimType( field.getPropertyValue() );
501 KimTypeService kimTypeService = KimFrameworkServiceLocator.getKimTypeService(kimType);
502 List<KimAttributeField> definitions = kimTypeService.getAttributeDefinitions(kimType.getId());
503 setAttrDefinitions(definitions);
504 for (KimAttributeField d : definitions) {
505 final AttributeDefinition definition = DataDictionaryTypeServiceHelper
506 .toKimAttributeDefinition(d);
507 List<Field> fields = new ArrayList<Field>();
508 Field typeField = new Field();
509
510 String attrDefnId = d.getId();
511 typeField.setFieldLabel(definition.getLabel());
512 typeField.setPropertyName("attributes(" + definition.getName()+")");
513 typeField.setPropertyValue(fieldValues.get(typeField.getPropertyName()));
514 if (definition.getControl().isSelect()) {
515 typeField.setFieldValidValues(definition.getOptionsFinder().getKeyValues());
516 typeField.setFieldType(Field.DROPDOWN);
517 } else if (definition.getControl().isText()){
518 typeField.setMaxLength(definition.getMaxLength());
519 if (definition.getControl().getSize() != null) {
520 typeField.setSize(definition.getControl().getSize());
521 }
522 typeField.setFieldType(Field.TEXT);
523 } else if (definition.getControl().isRadio()) {
524 typeField.setFieldValidValues(definition.getOptionsFinder().getKeyValues());
525 typeField.setFieldType(Field.RADIO);
526 } else if (definition.getControl().isCheckbox()) {
527 KeyValuesFinder finder = new IndicatorValuesFinder();
528 typeField.setFieldValidValues(finder.getKeyValues());
529 typeField.setFieldType(Field.RADIO);
530
531 } else if (definition.getControl().isHidden()) {
532 typeField.setFieldType(Field.HIDDEN);
533 } else if (definition.getControl().isLookupReadonly()) {
534 typeField.setFieldType(Field.LOOKUP_READONLY);
535 } else if (definition.getControl().isTextarea()) {
536 typeField.setMaxLength(definition.getMaxLength());
537 if (definition.getControl().getSize() != null) {
538 typeField.setSize(definition.getControl().getSize());
539 }
540 typeField.setFieldType(Field.TEXT_AREA);
541 }
542 fields.add(typeField);
543 returnRows.add(new Row(fields));
544 }
545 } else {
546 return getAttrRows();
547 }
548 } else if (field.getPropertyName().equals(KIM_TYPE_ID_PROPERTY_NAME) && StringUtils.isBlank(field.getPropertyValue())) {
549 setTypeId("");
550 }
551 }
552 return returnRows;
553 }
554
555 public List<Row> getGrpRows() {
556 return this.grpRows;
557 }
558
559 public void setGrpRows(List<Row> grpRows) {
560 this.grpRows = grpRows;
561 }
562
563 public List<KimAttributeField> getAttrDefinitions() {
564 return this.attrDefinitions;
565 }
566
567 public void setAttrDefinitions(List<KimAttributeField> attrDefinitions) {
568 this.attrDefinitions = attrDefinitions;
569 }
570
571 public List<Row> getAttrRows() {
572 return this.attrRows;
573 }
574
575 public void setAttrRows(List<Row> attrRows) {
576 this.attrRows = attrRows;
577 }
578
579 public String getTypeId() {
580 return this.typeId;
581 }
582
583 public void setTypeId(String typeId) {
584 this.typeId = typeId;
585 }
586
587
588
589
590
591
592
593 private String findAndConvertAttributeNamesToMappableProperty(String propertyName) {
594 if (isParamAttribute(propertyName)) {
595 return propertyName.replaceAll("attributes\\((.*?)\\)", "attributes\\[$1\\]");
596 } else {
597 return propertyName;
598 }
599 }
600
601 @Override
602 public void performClear(LookupForm lookupForm) {
603 super.performClear(lookupForm);
604 this.attrRows = new ArrayList<Row>();
605 }
606
607 }