001/** 002 * Copyright 2005-2013 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.krms.service.impl; 017 018import org.apache.commons.lang.StringUtils; 019import org.apache.ojb.broker.OptimisticLockException; 020import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader; 021import org.kuali.rice.core.api.util.tree.Node; 022import org.kuali.rice.core.api.util.tree.Tree; 023import org.kuali.rice.krad.bo.Note; 024import org.kuali.rice.krad.maintenance.MaintenanceDocument; 025import org.kuali.rice.krad.uif.UifConstants; 026import org.kuali.rice.krad.uif.component.BindingInfo; 027import org.kuali.rice.krad.uif.util.ObjectPropertyUtils; 028import org.kuali.rice.krad.uif.view.ViewModel; 029import org.kuali.rice.krad.util.KRADConstants; 030import org.kuali.rice.krad.web.form.MaintenanceDocumentForm; 031import org.kuali.rice.krms.api.KrmsConstants; 032import org.kuali.rice.krms.api.repository.RuleManagementService; 033import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition; 034import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition; 035import org.kuali.rice.krms.api.repository.context.ContextDefinition; 036import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplate; 037import org.kuali.rice.krms.api.repository.proposition.PropositionType; 038import org.kuali.rice.krms.api.repository.reference.ReferenceObjectBinding; 039import org.kuali.rice.krms.api.repository.rule.RuleDefinition; 040import org.kuali.rice.krms.api.repository.term.TermRepositoryService; 041import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition; 042import org.kuali.rice.krms.api.repository.type.KrmsTypeRepositoryService; 043import org.kuali.rice.krms.api.repository.typerelation.TypeTypeRelation; 044import org.kuali.rice.krms.builder.ComponentBuilder; 045import org.kuali.rice.krms.dto.AgendaEditor; 046import org.kuali.rice.krms.dto.AgendaTypeInfo; 047import org.kuali.rice.krms.dto.PropositionEditor; 048import org.kuali.rice.krms.dto.PropositionParameterEditor; 049import org.kuali.rice.krms.dto.RuleEditor; 050import org.kuali.rice.krms.dto.RuleManagementWrapper; 051import org.kuali.rice.krms.dto.RuleManager; 052import org.kuali.rice.krms.dto.RuleTypeInfo; 053import org.kuali.rice.krms.dto.TermEditor; 054import org.kuali.rice.krms.dto.TermParameterEditor; 055import org.kuali.rice.krms.service.RuleEditorMaintainable; 056import org.kuali.rice.krms.service.TemplateRegistry; 057import org.kuali.rice.krms.tree.RuleCompareTreeBuilder; 058import org.kuali.rice.krms.tree.RuleViewTreeBuilder; 059import org.kuali.rice.krms.tree.node.RuleEditorTreeNode; 060import org.kuali.rice.krms.util.AlphaIterator; 061import org.kuali.rice.krms.util.PropositionTreeUtil; 062import org.kuali.student.common.krms.exceptions.KRMSOptimisticLockingException; 063import org.kuali.student.common.uif.service.impl.KSMaintainableImpl; 064import org.kuali.student.r1.common.rice.StudentIdentityConstants; 065import org.kuali.student.r2.core.constants.KSKRMSServiceConstants; 066import org.slf4j.Logger; 067import org.slf4j.LoggerFactory; 068import org.springmodules.orm.ojb.OjbOperationException; 069 070import javax.xml.namespace.QName; 071import java.util.ArrayList; 072import java.util.Collection; 073import java.util.Collections; 074import java.util.Comparator; 075import java.util.HashMap; 076import java.util.LinkedHashMap; 077import java.util.LinkedList; 078import java.util.List; 079import java.util.Map; 080import java.util.Queue; 081 082/** 083 * {@link org.kuali.rice.krad.maintenance.Maintainable} 084 * 085 * @author Kuali Student Team (rice.collab@kuali.org) 086 */ 087public class RuleEditorMaintainableImpl extends KSMaintainableImpl implements RuleEditorMaintainable { 088 089 private static final long serialVersionUID = 1L; 090 091 private static final Logger LOG = LoggerFactory.getLogger(RuleEditorMaintainableImpl.class); 092 093 private transient RuleManagementService ruleManagementService; 094 private transient KrmsTypeRepositoryService krmsTypeRepositoryService; 095 private transient TermRepositoryService termRepositoryService; 096 097 private transient TemplateRegistry templateRegistry; 098 private AlphaIterator alphaIterator = new AlphaIterator(StringUtils.EMPTY); 099 100 public static final String NEW_AGENDA_EDITOR_DOCUMENT_TEXT = "New Agenda Editor Document"; 101 102 public String getViewTypeName() { 103 return "kuali.krms.agenda.type"; 104 } 105 106 /** 107 * Get the AgendaEditor out of the MaintenanceDocumentForm's newMaintainableObject 108 * 109 * @param model the MaintenanceDocumentForm 110 * @return the AgendaEditor 111 */ 112 private RuleEditor getRuleEditor(Object model) { 113 MaintenanceDocumentForm maintenanceDocumentForm = (MaintenanceDocumentForm) model; 114 return (RuleEditor) maintenanceDocumentForm.getDocument().getNewMaintainableObject().getDataObject(); 115 } 116 117 @Override 118 public Object retrieveObjectForEditOrCopy(MaintenanceDocument document, Map<String, String> dataObjectKeys) { 119 RuleManager dataObject = new RuleManagementWrapper(); 120 121 String refObjectId = dataObjectKeys.get("refObjectId"); 122 dataObject.setRefObjectId(refObjectId); 123 124 dataObject.setAgendas(this.getAgendasForRef("", refObjectId, null)); 125 126 dataObject.setCompareTree(RuleCompareTreeBuilder.initCompareTree()); 127 128 return dataObject; 129 } 130 131 protected List<AgendaEditor> getAgendasForRef(String discriminatorType, String refObjectId, String parentRefObjectId) { 132 // Initialize new array lists. 133 List<AgendaEditor> agendas = new ArrayList<AgendaEditor>(); 134 List<AgendaEditor> sortedAgendas = new ArrayList<AgendaEditor>(); 135 List<AgendaEditor> parentAgendas = new ArrayList<AgendaEditor>(); 136 137 // Get the list of existing agendas 138 LOG.info("Retrieving reference object binding for refobjectid: {}", refObjectId); 139 List<ReferenceObjectBinding> refObjectsBindings = this.getRuleManagementService().findReferenceObjectBindingsByReferenceObject(discriminatorType, refObjectId); 140 for (ReferenceObjectBinding referenceObjectBinding : refObjectsBindings) { 141 LOG.info("Retrieved reference object binding with id: {}", referenceObjectBinding.getReferenceObjectId()); 142 agendas.add(this.getAgendaEditor(referenceObjectBinding.getKrmsObjectId())); 143 } 144 145 // Get the list of parent agendas 146 List<ReferenceObjectBinding> parentRefObjects = this.getParentRefOjbects(parentRefObjectId); 147 for (ReferenceObjectBinding referenceObject : parentRefObjects) { 148 parentAgendas.add(this.getAgendaEditor(referenceObject.getKrmsObjectId())); 149 } 150 151 // Lookup existing agenda by type 152 for (AgendaTypeInfo agendaTypeInfo : this.getTypeRelationships()) { 153 AgendaEditor agenda = null; 154 for (AgendaEditor existingAgenda : agendas) { 155 if (existingAgenda.getTypeId().equals(agendaTypeInfo.getId())) { 156 agenda = existingAgenda; 157 break; 158 } 159 } 160 if (agenda == null) { 161 agenda = new AgendaEditor(); 162 agenda.setTypeId(agendaTypeInfo.getId()); 163 } 164 165 //Set the parent agenda. 166 for (AgendaEditor parent : parentAgendas) { 167 if (agenda.getTypeId().equals(agenda.getTypeId())) { 168 agenda.setParent(parent); 169 break; 170 } 171 } 172 173 agenda.setAgendaTypeInfo(agendaTypeInfo); 174 agenda.setRuleEditors(this.getRulesForAgendas(agenda)); 175 sortedAgendas.add(agenda); 176 } 177 178 return sortedAgendas; 179 } 180 181 protected AgendaEditor getAgendaEditor(String agendaId) { 182 LOG.info("Retrieving agenda for id: {}", agendaId); 183 AgendaDefinition agenda = this.getRuleManagementService().getAgenda(agendaId); 184 return new AgendaEditor(agenda); 185 } 186 187 public Map<String, RuleEditor> getRulesForAgendas(AgendaEditor agenda) { 188 189 //Get all existing rules. 190 List<RuleEditor> existingRules = null; 191 if (agenda.getId() != null) { 192 LOG.info("Retrieving agenda item for id: {}", agenda.getFirstItemId()); 193 AgendaItemDefinition firstItem = this.getRuleManagementService().getAgendaItem(agenda.getFirstItemId()); 194 existingRules = getRuleEditorsFromTree(firstItem, true); 195 } 196 197 //Get the parent rules 198 List<RuleEditor> parentRules = null; 199 if (agenda.getParent() != null) { 200 AgendaItemDefinition parentItem = this.getRuleManagementService().getAgendaItem(agenda.getParent().getFirstItemId()); 201 parentRules = getRuleEditorsFromTree(parentItem, false); 202 } 203 204 //Add dummy RuleEditors for empty rule types. 205 Map<String, RuleEditor> ruleEditors = new LinkedHashMap<String, RuleEditor>(); 206 for (RuleTypeInfo ruleType : agenda.getAgendaTypeInfo().getRuleTypes()) { 207 RuleEditor ruleEditor = null; 208 209 // Add all existing rules of this type. 210 if (existingRules != null) { 211 for (RuleEditor rule : existingRules) { 212 if (rule.getTypeId().equals(ruleType.getId()) && (!rule.isDummy())) { 213 ruleEditor = rule; 214 } 215 } 216 } 217 218 // If the ruletype does not exist, add an empty rule section 219 if (ruleEditor == null) { 220 ruleEditor = createDummyRuleEditor(ruleType.getId()); 221 } 222 223 ruleEditor.setKey((String) alphaIterator.next()); 224 ruleEditor.setRuleTypeInfo(ruleType); 225 ruleEditors.put(ruleEditor.getKey(), ruleEditor); 226 227 //Set the parent agenda. 228 if (parentRules != null) { 229 for (RuleEditor parent : parentRules) { 230 if (ruleEditor.getTypeId().equals(parent.getTypeId())) { 231 ruleEditor.setParent(parent); 232 break; 233 } 234 } 235 } 236 } 237 238 return ruleEditors; 239 } 240 241 protected RuleEditor createDummyRuleEditor(String ruleTypeId) { 242 RuleEditor ruleEditor = new RuleEditor(); 243 ruleEditor.setDummy(true); 244 ruleEditor.setTypeId(ruleTypeId); 245 return ruleEditor; 246 } 247 248 protected List<RuleEditor> getRuleEditorsFromTree(AgendaItemDefinition agendaItem, boolean initProps) { 249 250 List<RuleEditor> rules = new ArrayList<RuleEditor>(); 251 if (agendaItem.getRule() != null) { 252 RuleEditor ruleEditor = new RuleEditor(agendaItem.getRule()); 253 if (initProps) { 254 this.initPropositionEditor(ruleEditor.getPropositionEditor()); 255 ruleEditor.setViewTree(this.getViewTreeBuilder().buildTree(ruleEditor)); 256 } 257 rules.add(ruleEditor); 258 } 259 260 if (agendaItem.getWhenTrue() != null) { 261 rules.addAll(getRuleEditorsFromTree(agendaItem.getWhenTrue(), initProps)); 262 } 263 264 return rules; 265 } 266 267 /** 268 * Override this method to return the reference object id of the parent object. 269 * 270 * @param parentRefObjectId 271 * @return 272 */ 273 @Override 274 public List<ReferenceObjectBinding> getParentRefOjbects(String parentRefObjectId) { 275 return null; 276 } 277 278 protected RuleViewTreeBuilder getViewTreeBuilder() { 279 return new RuleViewTreeBuilder(); 280 } 281 282 /** 283 * Setup a map with all the type information required to build an agenda management page. 284 * 285 * @return 286 */ 287 protected List<AgendaTypeInfo> getTypeRelationships() { 288 List<AgendaTypeInfo> agendaTypeInfos = new ArrayList<AgendaTypeInfo>(); 289 290 // Get Instruction Usage Id 291 String instructionUsageId = getRuleManagementService().getNaturalLanguageUsageByNameAndNamespace(KSKRMSServiceConstants.KRMS_NL_TYPE_INSTRUCTION, 292 StudentIdentityConstants.KS_NAMESPACE_CD).getId(); 293 294 // Get Description Usage Id 295 String descriptionUsageId = getRuleManagementService().getNaturalLanguageUsageByNameAndNamespace(KSKRMSServiceConstants.KRMS_NL_TYPE_DESCRIPTION, 296 StudentIdentityConstants.KS_NAMESPACE_CD).getId(); 297 298 // Get the super type. 299 KrmsTypeDefinition requisitesType = this.getKrmsTypeRepositoryService().getTypeByName(StudentIdentityConstants.KS_NAMESPACE_CD, this.getViewTypeName()); 300 301 // Get all agenda types linked to super type. 302 List<TypeTypeRelation> agendaRelationships = this.getSortedTypeRelationshipsForTypeId(requisitesType.getId()); 303 for (TypeTypeRelation agendaRelationship : agendaRelationships) { 304 AgendaTypeInfo agendaTypeInfo = new AgendaTypeInfo(); 305 agendaTypeInfo.setId(agendaRelationship.getToTypeId()); 306 KrmsTypeDefinition agendaType = this.getKrmsTypeRepositoryService().getTypeById(agendaTypeInfo.getId()); 307 agendaTypeInfo.setType(agendaType.getName()); 308 agendaTypeInfo.setDescription(this.getDescriptionForTypeAndUsage(agendaRelationship.getToTypeId(), descriptionUsageId)); 309 310 List<RuleTypeInfo> ruleTypes = new ArrayList<RuleTypeInfo>(); 311 List<TypeTypeRelation> sortedRuleRelationships = this.getSortedTypeRelationshipsForTypeId(agendaRelationship.getToTypeId()); 312 for (TypeTypeRelation ruleRelationship : sortedRuleRelationships) { 313 RuleTypeInfo ruleTypeInfo = new RuleTypeInfo(); 314 ruleTypeInfo.setId(ruleRelationship.getToTypeId()); 315 KrmsTypeDefinition ruleType = this.getKrmsTypeRepositoryService().getTypeById(ruleTypeInfo.getId()); 316 ruleTypeInfo.setType(ruleType.getName()); 317 ruleTypeInfo.setDescription(this.getDescriptionForTypeAndUsage(ruleRelationship.getToTypeId(), descriptionUsageId)); 318 if (ruleTypeInfo.getDescription().isEmpty()) { 319 ruleTypeInfo.setDescription("Description is unset rule type"); 320 } 321 ruleTypeInfo.setInstruction(this.getDescriptionForTypeAndUsage(ruleRelationship.getToTypeId(), instructionUsageId)); 322 if (ruleTypeInfo.getInstruction().isEmpty()) { 323 ruleTypeInfo.setInstruction("Instruction is unset for rule type"); 324 } 325 // Add rule types to list. 326 ruleTypes.add(ruleTypeInfo); 327 } 328 agendaTypeInfo.setRuleTypes(ruleTypes); 329 agendaTypeInfos.add(agendaTypeInfo); 330 } 331 332 return agendaTypeInfos; 333 } 334 335 private List<TypeTypeRelation> getSortedTypeRelationshipsForTypeId(String typeId){ 336 // Get all rule types for each agenda type 337 List<TypeTypeRelation> relationships = new ArrayList<TypeTypeRelation>(); 338 relationships.addAll(this.getKrmsTypeRepositoryService().findTypeTypeRelationsByFromType(typeId)); 339 340 // order rules 341 Collections.sort(relationships, new Comparator<TypeTypeRelation>() { 342 @Override 343 public int compare(TypeTypeRelation typeTypeRelation1, TypeTypeRelation typeTypeRelation2) { 344 return typeTypeRelation1.getSequenceNumber().compareTo(typeTypeRelation2.getSequenceNumber()); 345 } 346 }); 347 return relationships; 348 } 349 350 private String getDescriptionForTypeAndUsage(String typeId, String usageId) { 351 NaturalLanguageTemplate template = null; 352 try { 353 template = getRuleManagementService().findNaturalLanguageTemplateByLanguageCodeTypeIdAndNluId("en", typeId, usageId); 354 return template.getTemplate(); 355 } catch (Exception e) { 356 return StringUtils.EMPTY; 357 } 358 } 359 360 /** 361 * {@inheritDoc} 362 */ 363 @Override 364 public void processAfterNew(MaintenanceDocument document, Map<String, String[]> requestParameters) { 365 super.processAfterNew(document, requestParameters); 366 document.getDocumentHeader().setDocumentDescription(NEW_AGENDA_EDITOR_DOCUMENT_TEXT); 367 } 368 369 @Override 370 public void processAfterEdit(MaintenanceDocument document, Map<String, String[]> requestParameters) { 371 super.processAfterEdit(document, requestParameters); 372 document.getDocumentHeader().setDocumentDescription("Modify Agenda Editor Document"); 373 } 374 375 @Override 376 public void saveDataObject() { 377 RuleManager ruleWrapper = (RuleManager) getDataObject(); 378 379 for (AgendaEditor agenda : ruleWrapper.getAgendas()) { 380 381 //Check if this agenda has anything to save 382 if (agenda.isDummyAgenda()) { 383 continue; 384 } 385 386 //Set the agenda name. 387 agenda.setName(ruleWrapper.getRefObjectId() + ":" + agenda.getAgendaTypeInfo().getId() + ":1"); 388 389 //Retrieve the context and set the id on the agenda. 390 if (agenda.getContextId() == null) { 391 ContextDefinition context = this.getRuleManagementService().getContextByNameAndNamespace("Course Requirements", ruleWrapper.getNamespace()); 392 agenda.setContextId(context.getId()); 393 } 394 395 //Create or update the agenda. 396 if (agenda.getId() == null) { 397 398 //Check if someone else has not created an agenda while this one was created. 399 if(this.getRuleManagementService().getAgendaByNameAndContextId(agenda.getName(), agenda.getContextId())!=null){ 400 throw new KRMSOptimisticLockingException(); 401 } 402 403 AgendaDefinition.Builder agendaBldr = AgendaDefinition.Builder.create(agenda); 404 AgendaDefinition agendaDfn = this.getRuleManagementService().createAgenda(agendaBldr.build()); 405 406 //Set the id and versionnumber for a possible update. 407 agenda.setId(agendaDfn.getId()); 408 agenda.setVersionNumber(agendaDfn.getVersionNumber()); 409 agenda.setFirstItemId(agendaDfn.getFirstItemId()); 410 411 //Create the reference object binding only on create agenda, no need to update. 412 ReferenceObjectBinding.Builder refBuilder = ReferenceObjectBinding.Builder.create("Agenda", 413 agendaDfn.getId(), ruleWrapper.getNamespace(), ruleWrapper.getRefDiscriminatorType(), ruleWrapper.getRefObjectId()); 414 this.getRuleManagementService().createReferenceObjectBinding(refBuilder.build()); 415 } 416 417 //Update the root item. 418 try { 419 420 //Set the first agenda item id and save the agenda items 421 AgendaItemDefinition firstItem = maintainAgendaItems(agenda, ruleWrapper.getRefObjectId() + ":", ruleWrapper.getNamespace()); 422 423 //If no more rules linked to agenda, delete it. 424 if (firstItem.getRule() == null) { 425 List<ReferenceObjectBinding> refObjectsBindings = this.getRuleManagementService().findReferenceObjectBindingsByReferenceObject(ruleWrapper.getRefDiscriminatorType(), ruleWrapper.getRefObjectId()); 426 for (ReferenceObjectBinding referenceObjectBinding : refObjectsBindings) { 427 if (referenceObjectBinding.getKrmsObjectId().equals(agenda.getId())) { 428 LOG.info("Deleting reference object binding for id: {}", referenceObjectBinding.getId()); 429 this.getRuleManagementService().deleteReferenceObjectBinding(referenceObjectBinding.getId()); 430 } 431 } 432 this.getRuleManagementService().deleteAgenda(agenda.getId()); 433 } 434 435 436 } catch (OjbOperationException e) { 437 //OptimisticLockException 438 if (e.getCause() instanceof OptimisticLockException) { 439 throw new KRMSOptimisticLockingException("RuleEditorMaintainableImpl Optimistic Lock exception",e); 440 } else { 441 throw e; 442 } 443 } 444 445 } 446 447 } 448 449 public AgendaItemDefinition maintainAgendaItems(AgendaEditor agenda, String namePrefix, String nameSpace) { 450 451 Queue<RuleDefinition.Builder> rules = new LinkedList<RuleDefinition.Builder>(); 452 for (RuleEditor rule : agenda.getRuleEditors().values()) { 453 if (!rule.isDummy()) { 454 rules.add(this.finRule(rule, namePrefix, nameSpace)); 455 } 456 } 457 458 AgendaItemDefinition.Builder rootItemBuilder = manageFirstItem(agenda); 459 460 AgendaItemDefinition.Builder itemToDelete = null; 461 AgendaItemDefinition.Builder itemBuilder = rootItemBuilder; 462 while (rules.peek() != null) { 463 itemBuilder.setRule(rules.poll()); 464 itemBuilder.setRuleId(itemBuilder.getRule().getId()); 465 if (rules.peek() != null) { 466 if(itemBuilder.getWhenTrue()==null){ 467 itemBuilder.setWhenTrue(AgendaItemDefinition.Builder.create(null, agenda.getId())); 468 } 469 itemBuilder = itemBuilder.getWhenTrue(); 470 } else { 471 itemToDelete = itemBuilder.getWhenTrue(); 472 itemBuilder.setWhenTrue(null); 473 } 474 } 475 476 return manageAgendaItems(agenda, rootItemBuilder, itemToDelete); 477 } 478 479 protected AgendaItemDefinition.Builder manageFirstItem(AgendaEditor agenda) { 480 AgendaItemDefinition.Builder rootItemBuilder; 481 if(agenda.getFirstItemId()!=null) { 482 AgendaItemDefinition firstItem = this.getRuleManagementService().getAgendaItem(agenda.getFirstItemId()); 483 rootItemBuilder = AgendaItemDefinition.Builder.create(firstItem); 484 rootItemBuilder.setRule(null); 485 rootItemBuilder.setRuleId(null); 486 } else { 487 rootItemBuilder = AgendaItemDefinition.Builder.create(null, agenda.getId()); 488 } 489 return rootItemBuilder; 490 } 491 492 protected AgendaItemDefinition manageAgendaItems(AgendaEditor agenda, AgendaItemDefinition.Builder rootItemBuilder, AgendaItemDefinition.Builder itemToDelete) { 493 //Update the root item. 494 AgendaItemDefinition agendaItem = rootItemBuilder.build(); 495 try { 496 if(agendaItem.getId()==null){ 497 agendaItem = this.getRuleManagementService().createAgendaItem(agendaItem); 498 agenda.setFirstItemId(agendaItem.getId()); 499 AgendaDefinition.Builder agendaBldr = AgendaDefinition.Builder.create(agenda); 500 this.getRuleManagementService().updateAgenda(agendaBldr.build()); 501 } else { 502 this.getRuleManagementService().updateAgendaItem(agendaItem); 503 } 504 505 //delete agendaitems not used. 506 if(itemToDelete!=null){ 507 this.deleteAgendaItems(itemToDelete.build()); 508 } 509 } catch (OjbOperationException e) { 510 //OptimisticLockException 511 if (e.getCause() instanceof OptimisticLockException) { 512 throw new KRMSOptimisticLockingException("Could not obtain OjbOperation ",e); 513 } else { 514 throw e; 515 } 516 } 517 518 //Delete orhpan rules 519 for (RuleEditor deletedRule : agenda.getDeletedRules()) { 520 this.getRuleManagementService().deleteRule(deletedRule.getId()); 521 } 522 return agendaItem; 523 } 524 525 public void deleteAgendaItems(AgendaItemDefinition agendaItem) { 526 if (agendaItem != null) { 527 //Update the agenda (hack so that it does not delete the rule.) 528 AgendaItemDefinition.Builder itemBuilder = AgendaItemDefinition.Builder.create(agendaItem.getId(), agendaItem.getAgendaId()); 529 itemBuilder.setVersionNumber(agendaItem.getVersionNumber()); 530 this.getRuleManagementService().updateAgendaItem(itemBuilder.build()); 531 532 //Delete the agenda item 533 this.getRuleManagementService().deleteAgendaItem(agendaItem.getId()); 534 deleteAgendaItems(agendaItem.getWhenFalse()); 535 deleteAgendaItems(agendaItem.getWhenTrue()); 536 deleteAgendaItems(agendaItem.getAlways()); 537 } 538 } 539 540 public RuleDefinition.Builder finRule(RuleEditor rule, String rulePrefix, String namespace) { 541 // handle saving new parameterized terms 542 if (rule.getPropositionEditor() != null) { 543 this.onSubmit(rule.getPropositionEditor()); 544 } 545 546 if (rule.getNamespace() == null) { 547 rule.setNamespace(namespace); 548 } 549 rule.setName(rulePrefix + rule.getRuleTypeInfo().getId() + ":1"); 550 551 //Check if someone else has not created a rule while this one was created. 552 if(rule.getId()==null){ 553 if(this.getRuleManagementService().getRuleByNameAndNamespace(rule.getName(), rule.getNamespace())!=null){ 554 throw new KRMSOptimisticLockingException(); 555 } 556 } 557 558 return RuleDefinition.Builder.create(rule); 559 } 560 561 public void onSubmit(PropositionEditor propositionEditor) { 562 if (PropositionType.SIMPLE.getCode().equalsIgnoreCase(propositionEditor.getPropositionTypeCode())) { 563 564 //Call onsubmit on the associated builder. 565 ComponentBuilder builder = this.getTemplateRegistry().getComponentBuilderForType(propositionEditor.getType()); 566 if (builder != null) { 567 builder.onSubmit(propositionEditor); 568 } 569 570 } else { 571 572 //If not a simple node, recursively finalize the child proposition editors. 573 for (PropositionEditor child : propositionEditor.getCompoundEditors()) { 574 onSubmit(child); 575 } 576 577 } 578 } 579 580 public void initPropositionEditor(PropositionEditor propositionEditor) { 581 if (propositionEditor == null) { 582 return; 583 } 584 585 if (PropositionType.SIMPLE.getCode().equalsIgnoreCase(propositionEditor.getPropositionTypeCode())) { 586 587 if (propositionEditor.getType() == null) { 588 KrmsTypeDefinition type = this.getKrmsTypeRepositoryService().getTypeById(propositionEditor.getTypeId()); 589 propositionEditor.setType(type.getName()); 590 } 591 592 Map<String, String> termParameters = this.getTermParameters(propositionEditor); 593 ComponentBuilder builder = this.getTemplateRegistry().getComponentBuilderForType(propositionEditor.getType()); 594 if (builder != null) { 595 builder.resolveTermParameters(propositionEditor, termParameters); 596 } 597 } else { 598 for (PropositionEditor child : propositionEditor.getCompoundEditors()) { 599 initPropositionEditor(child); 600 } 601 602 } 603 } 604 605 public Map<String, String> getTermParameters(PropositionEditor proposition) { 606 607 Map<String, String> termParameters = new HashMap<String, String>(); 608 if (proposition.getTerm() == null) { 609 PropositionParameterEditor termParameter = PropositionTreeUtil.getTermParameter(proposition.getParameters()); 610 if (termParameter != null) { 611 612 if (termParameter.getTermValue() == null) { 613 proposition.setTerm(new TermEditor()); 614 } else { 615 proposition.setTerm(new TermEditor(termParameter.getTermValue())); 616 } 617 618 } else { 619 return termParameters; 620 } 621 } 622 623 for (TermParameterEditor parameter : proposition.getTerm().getEditorParameters()) { 624 termParameters.put(parameter.getName(), parameter.getValue()); 625 } 626 627 return termParameters; 628 } 629 630 /** 631 * In the case of edit maintenance adds a new blank line to the old side 632 * <p/> 633 * 634 * @see org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl#processAfterAddLine(org.kuali.rice.krad.uif.view.ViewModel, Object, String, String, boolean) 635 */ 636 @Override 637 public void processAfterAddLine(ViewModel viewModel, Object addLine, String collectionId, String collectionPath, boolean isValidLine) { 638 // Check for maintenance documents in edit but exclude notes 639 if (viewModel instanceof MaintenanceDocumentForm && KRADConstants.MAINTENANCE_EDIT_ACTION.equals(((MaintenanceDocumentForm) viewModel).getMaintenanceAction()) && !(addLine instanceof Note)) { 640 641 // Figure out which rule is being edited 642 RuleEditor rule = getRuleEditor(viewModel); 643 // Figure out which proposition is being edited 644 Tree<RuleEditorTreeNode, String> propositionTree = rule.getEditTree(); 645 Node<RuleEditorTreeNode, String> editedPropositionNode = PropositionTreeUtil.findEditedProposition(propositionTree.getRootElement()); 646 647 BindingInfo bindingInfo = (BindingInfo) viewModel.getViewPostMetadata().getComponentPostData(collectionId, 648 UifConstants.PostMetadata.BINDING_INFO); 649 // get the old object's collection 650 Collection<Object> oldCollection = ObjectPropertyUtils 651 .getPropertyValue(editedPropositionNode.getData(), 652 bindingInfo.getBindingName()); 653 654 Class<?> collectionObjectClass = (Class<?>) viewModel.getViewPostMetadata().getComponentPostData(collectionId, 655 UifConstants.PostMetadata.COLL_OBJECT_CLASS); 656 try { 657 Object blankLine = collectionObjectClass.newInstance(); 658 //Add a blank line to the top of the collection 659 if (oldCollection instanceof List) { 660 ((List) oldCollection).add(0, blankLine); 661 } else { 662 oldCollection.add(blankLine); 663 } 664 } catch (Exception e) { 665 throw new RuntimeException("Unable to create new line instance for old maintenance object", e); 666 } 667 } 668 } 669 670 public RuleManagementService getRuleManagementService() { 671 if (ruleManagementService == null) { 672 ruleManagementService = (RuleManagementService) GlobalResourceLoader.getService(new QName(KrmsConstants.Namespaces.KRMS_NAMESPACE_2_0, "ruleManagementService")); 673 } 674 return ruleManagementService; 675 } 676 677 public KrmsTypeRepositoryService getKrmsTypeRepositoryService() { 678 if (krmsTypeRepositoryService == null) { 679 krmsTypeRepositoryService = (KrmsTypeRepositoryService) GlobalResourceLoader.getService(new QName(KrmsConstants.Namespaces.KRMS_NAMESPACE_2_0, "krmsTypeRepositoryService")); 680 } 681 return krmsTypeRepositoryService; 682 } 683 684 public TermRepositoryService getTermRepositoryService() { 685 if (termRepositoryService == null) { 686 termRepositoryService = (TermRepositoryService) GlobalResourceLoader.getService(new QName(KrmsConstants.Namespaces.KRMS_NAMESPACE_2_0, "termRepositoryService")); 687 } 688 return termRepositoryService; 689 } 690 691 private TemplateRegistry getTemplateRegistry() { 692 if (templateRegistry == null) { 693 templateRegistry = (TemplateRegistry) GlobalResourceLoader.getService(new QName("http://student.kuali.org/wsdl/templateResolverService", "templateResolverService")); 694 } 695 return templateRegistry; 696 } 697}