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.MaintenanceDocumentForm;
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(
165                         termSpecId, namespace);
166 
167         TermResolverDefinition simplestResolver = null;
168 
169         for (TermResolverDefinition resolver : resolvers) {
170             if (simplestResolver == null ||
171                     simplestResolver.getParameterNames().size() < resolver.getParameterNames().size()) {
172                 simplestResolver = resolver;
173             }
174         }
175 
176         return simplestResolver;
177     }
178 
179     
180 
181 
182 
183 
184     private Node<RuleTreeNode, String> findEditedProposition(Node<RuleTreeNode, String> node) {
185         Node<RuleTreeNode, String> result = null;
186         if (node.getData() != null && node.getData().getProposition() != null &&
187                 node.getData().getProposition().getEditMode()) {
188             result = node;
189         } else {
190             for (Node<RuleTreeNode, String> child : node.getChildren()) {
191                 result = findEditedProposition(child);
192                 if (result != null) break;
193             }
194         }
195         return result;
196     }
197 
198     
199 
200 
201 
202 
203     private AgendaEditor getAgendaEditor(Object model) {
204         MaintenanceDocumentForm maintenanceForm = (MaintenanceDocumentForm)model;
205         return (AgendaEditor)maintenanceForm.getDocument().getNewMaintainableObject().getDataObject();
206     }
207 
208     public List<RemotableAttributeField> retrieveRuleActionCustomAttributes(View view, Object model, Container container) {
209         AgendaEditor agendaEditor = getAgendaEditor((MaintenanceDocumentForm) model);
210         return krmsRetriever.retrieveRuleActionCustomAttributes(agendaEditor);
211     }
212 
213     
214 
215 
216     public List<RemotableAttributeField> retrieveRuleCustomAttributes(View view, Object model, Container container) {
217         AgendaEditor agendaEditor = getAgendaEditor((MaintenanceDocumentForm) model);
218         return krmsRetriever.retrieveRuleCustomAttributes(agendaEditor);
219     }
220 
221     @Override
222     public Object retrieveObjectForEditOrCopy(MaintenanceDocument document, Map<String, String> dataObjectKeys) {
223         Object dataObject = null;
224 
225         try {
226             
227             AgendaEditor agendaEditor = new AgendaEditor();
228             AgendaBo agenda = getLookupService().findObjectBySearch(((AgendaEditor) getDataObject()).getAgenda().getClass(), dataObjectKeys);
229             if (KRADConstants.MAINTENANCE_COPY_ACTION.equals(getMaintenanceAction())) {
230                 String dateTimeStamp = (new Date()).getTime() + "";
231                 String newAgendaName = AgendaItemBo.COPY_OF_TEXT + agenda.getName() + " " + dateTimeStamp;
232 
233                 AgendaBo copiedAgenda = agenda.copyAgenda(newAgendaName, dateTimeStamp);
234 
235                 document.getDocumentHeader().setDocumentDescription(NEW_AGENDA_EDITOR_DOCUMENT_TEXT);
236                 document.setFieldsClearedOnCopy(true);
237                 agendaEditor.setAgenda(copiedAgenda);
238             } else {
239                 
240                 
241                 agendaEditor.setAgenda(agenda);
242             }
243             agendaEditor.setCustomAttributesMap(agenda.getAttributes());
244 
245 
246             
247             agendaEditor.setNamespace(agenda.getContext().getNamespace());
248             agendaEditor.setContextName(agenda.getContext().getName());
249 
250             dataObject = agendaEditor;
251         } catch (ClassNotPersistenceCapableException ex) {
252             if (!document.getOldMaintainableObject().isExternalBusinessObject()) {
253                 throw new RuntimeException("Data Object Class: " + getDataObjectClass() +
254                         " is not persistable and is not externalizable - configuration error");
255             }
256             
257         }
258 
259         return dataObject;
260     }
261 
262     
263 
264 
265 
266     private SequenceAccessorService getSequenceAccessorService() {
267         if ( sequenceAccessorService == null ) {
268             sequenceAccessorService = KRADServiceLocator.getSequenceAccessorService();
269         }
270         return sequenceAccessorService;
271     }
272     
273 
274 
275     @Override
276     public void processAfterNew(MaintenanceDocument document, Map<String, String[]> requestParameters) {
277         super.processAfterNew(document, requestParameters);
278         document.getDocumentHeader().setDocumentDescription(NEW_AGENDA_EDITOR_DOCUMENT_TEXT);
279     }
280 
281     @Override
282     public void processAfterEdit(MaintenanceDocument document, Map<String, String[]> requestParameters) {
283         super.processAfterEdit(document, requestParameters);
284         document.getDocumentHeader().setDocumentDescription("Modify Agenda Editor Document");
285     }
286 
287     @Override
288     public void prepareForSave() {
289         
290         AgendaEditor agendaEditor = (AgendaEditor) getDataObject();
291         agendaEditor.getAgenda().setAttributes(agendaEditor.getCustomAttributesMap());
292     }
293 
294     @Override
295     public void saveDataObject() {
296         AgendaBo agendaBo = ((AgendaEditor) getDataObject()).getAgenda();
297 
298         
299         for (AgendaItemBo agendaItem : agendaBo.getItems()) {
300             PropositionBo propositionBo = agendaItem.getRule().getProposition();
301             if (propositionBo != null) {
302                 saveNewParameterizedTerms(propositionBo);
303             }
304         }
305 
306         if (agendaBo instanceof PersistableBusinessObject) {
307         	        	
308             Map<String,String> primaryKeys = new HashMap<String, String>();
309             primaryKeys.put("id", agendaBo.getId());
310             AgendaBo blah = getBusinessObjectService().findByPrimaryKey(AgendaBo.class, primaryKeys);
311             
312         	
313         	
314         	
315         	preOrderTraversalDelete(getFirstAgendaItem(blah));
316             
317             getBusinessObjectService().delete(blah);
318 
319             getBusinessObjectService().linkAndSave(agendaBo);
320         } else {
321             throw new RuntimeException(
322                     "Cannot save object of type: " + agendaBo + " with business object service");
323         }
324     }
325     
326     private AgendaItemBo getFirstAgendaItem(AgendaBo agenda) {
327     	String firstItemId = agenda.getFirstItemId();
328     	if (firstItemId == null) {
329     		return null;
330     	}
331     	for (AgendaItemBo item : agenda.getItems()) {
332     		if (item.getId().equals(firstItemId)) {
333     			return item;
334     		}
335     	}
336     	throw new IllegalStateException("Failed to locate the first agenda item on the agenda with an id of " + firstItemId + ", agenda id is " + agenda.getId());
337     }
338     
339     private void preOrderTraversalDelete(AgendaItemBo agendaItem) {
340     	if (agendaItem == null) {
341     		return;
342     	}
343     	getBusinessObjectService().delete(agendaItem);
344     	if (agendaItem.getWhenFalse() != null) {
345 			preOrderTraversalDelete(agendaItem.getWhenFalse());
346 		}
347     	if (agendaItem.getWhenTrue() != null) {
348     		preOrderTraversalDelete(agendaItem.getWhenTrue());
349     	}    	
350     	preOrderTraversalDelete(agendaItem.getAlways());
351     }
352         
353     
354 
355 
356 
357     private void saveNewParameterizedTerms(PropositionBo propositionBo) {
358         if (StringUtils.isBlank(propositionBo.getCompoundOpCode())) {
359             
360             String termId = propositionBo.getParameters().get(0).getValue();
361             if (termId.startsWith(KrmsImplConstants.PARAMETERIZED_TERM_PREFIX)) {
362                 String termSpecId = termId.substring(KrmsImplConstants.PARAMETERIZED_TERM_PREFIX.length());
363                 
364                 TermBo newTerm = new TermBo();
365                 newTerm.setDescription(propositionBo.getNewTermDescription());
366                 newTerm.setSpecificationId(termSpecId);
367                 newTerm.setId(KRADServiceLocator.getSequenceAccessorService().getNextAvailableSequenceNumber("KRMS_TERM_S").toString());
368 
369                 List<TermParameterBo> params = new ArrayList<TermParameterBo>();
370                 for (Map.Entry<String, String> entry : propositionBo.getTermParameters().entrySet()) {
371                     TermParameterBo param = new TermParameterBo();
372                     param.setTermId(newTerm.getId());
373                     param.setName(entry.getKey());
374                     param.setValue(entry.getValue());
375                     param.setId(KRADServiceLocator.getSequenceAccessorService().getNextAvailableSequenceNumber("KRMS_TERM_PARM_S").toString());
376 
377                     params.add(param);
378                 }
379 
380                 newTerm.setParameters(params);
381 
382                 KRADServiceLocator.getBusinessObjectService().linkAndSave(newTerm);
383                 propositionBo.getParameters().get(0).setValue(newTerm.getId());
384             }
385         } else {
386             
387             for (PropositionBo childProp : propositionBo.getCompoundComponents()) {
388                 saveNewParameterizedTerms(childProp);
389             }
390         }
391     }
392 
393     
394 
395 
396 
397 
398 
399     private Map<String, KrmsAttributeDefinition> buildAttributeDefinitionMap(String agendaTypeId) {
400         KrmsAttributeDefinitionService attributeDefinitionService = KrmsRepositoryServiceLocator.getKrmsAttributeDefinitionService();
401 
402         
403         Map<String, KrmsAttributeDefinition> attributeDefinitionMap = new HashMap<String, KrmsAttributeDefinition>();
404 
405         List<KrmsAttributeDefinition> attributeDefinitions =
406                 attributeDefinitionService.findAttributeDefinitionsByType(agendaTypeId);
407 
408         for (KrmsAttributeDefinition attributeDefinition : attributeDefinitions) {
409             attributeDefinitionMap.put(attributeDefinition.getName(), attributeDefinition);
410         }
411         return attributeDefinitionMap;
412     }
413 
414     @Override
415     public boolean isOldDataObjectInDocument() {
416         boolean isOldDataObjectInExistence = true;
417 
418         if (getDataObject() == null) {
419             isOldDataObjectInExistence = false;
420         } else {
421             
422             Map<String, ?> keyFieldValues = getDataObjectMetaDataService().getPrimaryKeyFieldValues(((AgendaEditor) getDataObject()).getAgenda());
423             for (Object keyValue : keyFieldValues.values()) {
424                 if (keyValue == null) {
425                     isOldDataObjectInExistence = false;
426                 } else if ((keyValue instanceof String) && StringUtils.isBlank((String) keyValue)) {
427                     isOldDataObjectInExistence = false;
428                 }
429 
430                 if (!isOldDataObjectInExistence) {
431                     break;
432                 }
433             }
434         }
435 
436         return isOldDataObjectInExistence;
437     }
438 
439     
440     @Override
441     public Class getDataObjectClass() {
442         return AgendaBo.class;
443     }
444 
445     @Override
446     protected void processBeforeAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) {
447         AgendaEditor agendaEditor = getAgendaEditor(model);
448         if (addLine instanceof ActionBo) {
449             ((ActionBo) addLine).setNamespace(agendaEditor.getAgendaItemLine().getRule().getNamespace());
450         }
451 
452         super.processBeforeAddLine(view, collectionGroup, model, addLine);
453     }
454 }