1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krms.impl.ui;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException;
21 import org.kuali.rice.core.api.uif.DataType;
22 import org.kuali.rice.core.api.uif.RemotableAttributeField;
23 import org.kuali.rice.core.api.uif.RemotableTextInput;
24 import org.kuali.rice.core.api.util.tree.Node;
25 import org.kuali.rice.core.api.util.tree.Tree;
26 import org.kuali.rice.krad.bo.PersistableBusinessObject;
27 import org.kuali.rice.krad.maintenance.MaintenanceDocument;
28 import org.kuali.rice.krad.maintenance.Maintainable;
29 import org.kuali.rice.krad.maintenance.MaintainableImpl;
30 import org.kuali.rice.krad.service.BusinessObjectService;
31 import org.kuali.rice.krad.service.KRADServiceLocator;
32 import org.kuali.rice.krad.service.SequenceAccessorService;
33 import org.kuali.rice.krad.uif.container.CollectionGroup;
34 import org.kuali.rice.krad.uif.container.Container;
35 import org.kuali.rice.krad.uif.view.View;
36 import org.kuali.rice.krad.util.KRADConstants;
37 import org.kuali.rice.krad.web.form.MaintenanceForm;
38 import org.kuali.rice.krms.api.repository.term.TermResolverDefinition;
39 import org.kuali.rice.krms.api.repository.type.KrmsAttributeDefinition;
40 import org.kuali.rice.krms.impl.repository.ActionBo;
41 import org.kuali.rice.krms.impl.repository.AgendaBo;
42 import org.kuali.rice.krms.impl.repository.AgendaItemBo;
43 import org.kuali.rice.krms.impl.repository.ContextBoService;
44 import org.kuali.rice.krms.impl.repository.KrmsAttributeDefinitionService;
45 import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator;
46 import org.kuali.rice.krms.impl.repository.PropositionBo;
47 import org.kuali.rice.krms.impl.repository.PropositionParameterBo;
48 import org.kuali.rice.krms.impl.repository.RuleBo;
49 import org.kuali.rice.krms.impl.repository.TermBo;
50 import org.kuali.rice.krms.impl.repository.TermParameterBo;
51 import org.kuali.rice.krms.impl.util.KrmsImplConstants;
52 import org.kuali.rice.krms.impl.util.KrmsRetriever;
53
54 import java.util.ArrayList;
55 import java.util.Collections;
56 import java.util.Date;
57 import java.util.HashMap;
58 import java.util.List;
59 import java.util.Map;
60
61
62
63
64
65
66
67 public class AgendaEditorMaintainable extends MaintainableImpl {
68
69 private static final long serialVersionUID = 1L;
70
71 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AgendaEditorMaintainable.class);
72
73 public static final String NEW_AGENDA_EDITOR_DOCUMENT_TEXT = "New Agenda Editor Document";
74
75 private transient SequenceAccessorService sequenceAccessorService;
76
77 private transient KrmsRetriever krmsRetriever = new KrmsRetriever();
78
79
80
81
82 public BusinessObjectService getBoService() {
83 return KRADServiceLocator.getBusinessObjectService();
84 }
85
86
87
88
89 private ContextBoService getContextBoService() {
90 return KrmsRepositoryServiceLocator.getContextBoService();
91 }
92
93 public List<RemotableAttributeField> retrieveAgendaCustomAttributes(View view, Object model, Container container) {
94 AgendaEditor agendaEditor = getAgendaEditor(model);
95 return krmsRetriever.retrieveAgendaCustomAttributes(agendaEditor);
96 }
97
98
99
100
101
102 public List<RemotableAttributeField> retrieveTermParameters(View view, Object model, Container container) {
103
104 List<RemotableAttributeField> results = new ArrayList<RemotableAttributeField>();
105
106 AgendaEditor agendaEditor = getAgendaEditor(model);
107
108
109 RuleBo rule = agendaEditor.getAgendaItemLine().getRule();
110
111 Tree<RuleTreeNode, String> propositionTree = rule.getPropositionTree();
112 Node<RuleTreeNode, String> editedPropositionNode = findEditedProposition(propositionTree.getRootElement());
113
114 if (editedPropositionNode != null) {
115 PropositionBo propositionBo = editedPropositionNode.getData().getProposition();
116 if (StringUtils.isEmpty(propositionBo.getCompoundOpCode()) && CollectionUtils.size(propositionBo.getParameters()) > 0) {
117
118 PropositionParameterBo param = propositionBo.getParameters().get(0);
119 if (param.getValue().startsWith(KrmsImplConstants.PARAMETERIZED_TERM_PREFIX)) {
120 String termSpecId = param.getValue().substring(KrmsImplConstants.PARAMETERIZED_TERM_PREFIX.length());
121 TermResolverDefinition simplestResolver = getSimplestTermResolver(termSpecId, rule.getNamespace());
122
123
124 if (simplestResolver != null) {
125 List<String> parameterNames = new ArrayList<String>(simplestResolver.getParameterNames());
126 Collections.sort(parameterNames);
127
128 for (String parameterName : parameterNames) {
129
130 RemotableTextInput.Builder controlBuilder = RemotableTextInput.Builder.create();
131 controlBuilder.setSize(64);
132
133 RemotableAttributeField.Builder builder = RemotableAttributeField.Builder.create(parameterName);
134
135 builder.setRequired(true);
136 builder.setDataType(DataType.STRING);
137 builder.setControl(controlBuilder);
138 builder.setLongLabel(parameterName);
139 builder.setShortLabel(parameterName);
140 builder.setMinLength(Integer.valueOf(1));
141 builder.setMaxLength(Integer.valueOf(64));
142
143 results.add(builder.build());
144 }
145 }
146 }
147 }
148 }
149
150 return results;
151 }
152
153
154
155
156
157
158
159
160 static TermResolverDefinition getSimplestTermResolver(String termSpecId,
161 String namespace) {
162
163 List<TermResolverDefinition> resolvers =
164 KrmsRepositoryServiceLocator.getTermBoService().findTermResolversByOutputId(termSpecId, namespace);
165
166 TermResolverDefinition simplestResolver = null;
167
168 for (TermResolverDefinition resolver : resolvers) {
169 if (simplestResolver == null ||
170 simplestResolver.getParameterNames().size() < resolver.getParameterNames().size()) {
171 simplestResolver = resolver;
172 }
173 }
174
175 return simplestResolver;
176 }
177
178
179
180
181
182
183 private Node<RuleTreeNode, String> findEditedProposition(Node<RuleTreeNode, String> node) {
184 Node<RuleTreeNode, String> result = null;
185 if (node.getData() != null && node.getData().getProposition() != null &&
186 node.getData().getProposition().getEditMode()) {
187 result = node;
188 } else {
189 for (Node<RuleTreeNode, String> child : node.getChildren()) {
190 result = findEditedProposition(child);
191 if (result != null) break;
192 }
193 }
194 return result;
195 }
196
197
198
199
200
201
202 private AgendaEditor getAgendaEditor(Object model) {
203 MaintenanceForm maintenanceForm = (MaintenanceForm)model;
204 return (AgendaEditor)maintenanceForm.getDocument().getNewMaintainableObject().getDataObject();
205 }
206
207 public List<RemotableAttributeField> retrieveRuleActionCustomAttributes(View view, Object model, Container container) {
208 AgendaEditor agendaEditor = getAgendaEditor((MaintenanceForm) model);
209 return krmsRetriever.retrieveRuleActionCustomAttributes(agendaEditor);
210 }
211
212
213
214
215 public List<RemotableAttributeField> retrieveRuleCustomAttributes(View view, Object model, Container container) {
216 AgendaEditor agendaEditor = getAgendaEditor((MaintenanceForm) model);
217 return krmsRetriever.retrieveRuleCustomAttributes(agendaEditor);
218 }
219
220 @Override
221 public Object retrieveObjectForEditOrCopy(MaintenanceDocument document, Map<String, String> dataObjectKeys) {
222 Object dataObject = null;
223
224 try {
225
226 AgendaEditor agendaEditor = new AgendaEditor();
227 AgendaBo agenda = getLookupService().findObjectBySearch(((AgendaEditor) getDataObject()).getAgenda().getClass(), dataObjectKeys);
228 if (KRADConstants.MAINTENANCE_COPY_ACTION.equals(getMaintenanceAction())) {
229 String dateTimeStamp = (new Date()).getTime() + "";
230 String newAgendaName = AgendaItemBo.COPY_OF_TEXT + agenda.getName() + " " + dateTimeStamp;
231
232 AgendaBo copiedAgenda = agenda.copyAgenda(newAgendaName, dateTimeStamp);
233
234 document.getDocumentHeader().setDocumentDescription(NEW_AGENDA_EDITOR_DOCUMENT_TEXT);
235 document.setFieldsClearedOnCopy(true);
236 agendaEditor.setAgenda(copiedAgenda);
237 } else {
238
239
240 agendaEditor.setAgenda(agenda);
241 }
242 agendaEditor.setCustomAttributesMap(agenda.getAttributes());
243
244
245
246 agendaEditor.setNamespace(agenda.getContext().getNamespace());
247 agendaEditor.setContextName(agenda.getContext().getName());
248
249 dataObject = agendaEditor;
250 } catch (ClassNotPersistenceCapableException ex) {
251 if (!document.getOldMaintainableObject().isExternalBusinessObject()) {
252 throw new RuntimeException("Data Object Class: " + getDataObjectClass() +
253 " is not persistable and is not externalizable - configuration error");
254 }
255
256 }
257
258 return dataObject;
259 }
260
261
262
263
264
265 private SequenceAccessorService getSequenceAccessorService() {
266 if ( sequenceAccessorService == null ) {
267 sequenceAccessorService = KRADServiceLocator.getSequenceAccessorService();
268 }
269 return sequenceAccessorService;
270 }
271
272
273
274 @Override
275 public void processAfterNew(MaintenanceDocument document, Map<String, String[]> requestParameters) {
276 super.processAfterNew(document, requestParameters);
277 document.getDocumentHeader().setDocumentDescription(NEW_AGENDA_EDITOR_DOCUMENT_TEXT);
278 }
279
280 @Override
281 public void processAfterEdit(MaintenanceDocument document, Map<String, String[]> requestParameters) {
282 super.processAfterEdit(document, requestParameters);
283 document.getDocumentHeader().setDocumentDescription("Modify Agenda Editor Document");
284 }
285
286 @Override
287 public void prepareForSave() {
288
289 AgendaEditor agendaEditor = (AgendaEditor) getDataObject();
290 agendaEditor.getAgenda().setAttributes(agendaEditor.getCustomAttributesMap());
291 }
292
293 @Override
294 public void saveDataObject() {
295 AgendaBo agendaBo = ((AgendaEditor) getDataObject()).getAgenda();
296
297
298 for (AgendaItemBo agendaItem : agendaBo.getItems()) {
299 PropositionBo propositionBo = agendaItem.getRule().getProposition();
300 if (propositionBo != null) {
301 saveNewParameterizedTerms(propositionBo);
302 }
303 }
304
305 if (agendaBo instanceof PersistableBusinessObject) {
306 Map<String,String> primaryKeys = new HashMap<String, String>();
307 primaryKeys.put("id", agendaBo.getId());
308 AgendaBo blah = getBusinessObjectService().findByPrimaryKey(AgendaBo.class, primaryKeys);
309 getBusinessObjectService().delete(blah);
310
311 getBusinessObjectService().linkAndSave(agendaBo);
312 } else {
313 throw new RuntimeException(
314 "Cannot save object of type: " + agendaBo + " with business object service");
315 }
316 }
317
318
319
320
321
322 private void saveNewParameterizedTerms(PropositionBo propositionBo) {
323 if (StringUtils.isBlank(propositionBo.getCompoundOpCode())) {
324
325 if (!propositionBo.getParameters().isEmpty() && propositionBo.getParameters().get(0).getValue().startsWith(KrmsImplConstants.PARAMETERIZED_TERM_PREFIX)) {
326 String termId = propositionBo.getParameters().get(0).getValue();
327 String termSpecId = termId.substring(KrmsImplConstants.PARAMETERIZED_TERM_PREFIX.length());
328
329 TermBo newTerm = new TermBo();
330 newTerm.setDescription(propositionBo.getNewTermDescription());
331 newTerm.setSpecificationId(termSpecId);
332 newTerm.setId(KRADServiceLocator.getSequenceAccessorService().getNextAvailableSequenceNumber(
333 KrmsMaintenanceConstants.Sequences.TERM_SPECIFICATION, TermBo.class).toString());
334
335 List<TermParameterBo> params = new ArrayList<TermParameterBo>();
336 for (Map.Entry<String, String> entry : propositionBo.getTermParameters().entrySet()) {
337 TermParameterBo param = new TermParameterBo();
338 param.setTermId(newTerm.getId());
339 param.setName(entry.getKey());
340 param.setValue(entry.getValue());
341 param.setId(KRADServiceLocator.getSequenceAccessorService().getNextAvailableSequenceNumber(
342 KrmsMaintenanceConstants.Sequences.TERM_PARAMETER, TermParameterBo.class).toString());
343
344 params.add(param);
345 }
346
347 newTerm.setParameters(params);
348
349 KRADServiceLocator.getBusinessObjectService().linkAndSave(newTerm);
350 propositionBo.getParameters().get(0).setValue(newTerm.getId());
351 }
352 } else {
353
354 for (PropositionBo childProp : propositionBo.getCompoundComponents()) {
355 saveNewParameterizedTerms(childProp);
356 }
357 }
358 }
359
360
361
362
363
364
365
366 private Map<String, KrmsAttributeDefinition> buildAttributeDefinitionMap(String agendaTypeId) {
367 KrmsAttributeDefinitionService attributeDefinitionService = KrmsRepositoryServiceLocator.getKrmsAttributeDefinitionService();
368
369
370 Map<String, KrmsAttributeDefinition> attributeDefinitionMap = new HashMap<String, KrmsAttributeDefinition>();
371
372 List<KrmsAttributeDefinition> attributeDefinitions =
373 attributeDefinitionService.findAttributeDefinitionsByType(agendaTypeId);
374
375 for (KrmsAttributeDefinition attributeDefinition : attributeDefinitions) {
376 attributeDefinitionMap.put(attributeDefinition.getName(), attributeDefinition);
377 }
378 return attributeDefinitionMap;
379 }
380
381 @Override
382 public boolean isOldDataObjectInDocument() {
383 boolean isOldDataObjectInExistence = true;
384
385 if (getDataObject() == null) {
386 isOldDataObjectInExistence = false;
387 } else {
388
389 Map<String, ?> keyFieldValues = getDataObjectMetaDataService().getPrimaryKeyFieldValues(((AgendaEditor) getDataObject()).getAgenda());
390 for (Object keyValue : keyFieldValues.values()) {
391 if (keyValue == null) {
392 isOldDataObjectInExistence = false;
393 } else if ((keyValue instanceof String) && StringUtils.isBlank((String) keyValue)) {
394 isOldDataObjectInExistence = false;
395 }
396
397 if (!isOldDataObjectInExistence) {
398 break;
399 }
400 }
401 }
402
403 return isOldDataObjectInExistence;
404 }
405
406
407 @Override
408 public Class getDataObjectClass() {
409 return AgendaBo.class;
410 }
411
412 @Override
413 public boolean isLockable() {
414 return true;
415 }
416
417 @Override
418 public PersistableBusinessObject getPersistableBusinessObject() {
419 return ((AgendaEditor) getDataObject()).getAgenda();
420 }
421
422 @Override
423 protected void processBeforeAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) {
424 AgendaEditor agendaEditor = getAgendaEditor(model);
425 if (addLine instanceof ActionBo) {
426 ((ActionBo) addLine).setNamespace(agendaEditor.getAgendaItemLine().getRule().getNamespace());
427 }
428
429 super.processBeforeAddLine(view, collectionGroup, model, addLine);
430 }
431 }