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 }