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