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