1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.student.lum.program.client.requirements;
17
18 import java.util.HashMap;
19 import java.util.List;
20 import java.util.Map;
21
22 import org.kuali.student.r1.common.assembly.data.Metadata;
23 import org.kuali.student.r1.core.statement.dto.ReqCompFieldTypeInfo;
24 import org.kuali.student.r1.core.statement.dto.ReqComponentTypeInfo;
25 import org.kuali.student.r1.core.statement.dto.ReqCompFieldInfo;
26 import org.kuali.student.r1.core.statement.dto.ReqComponentInfo;
27 import org.kuali.student.r1.core.statement.dto.StatementOperatorTypeKey;
28 import org.kuali.student.r1.core.statement.dto.StatementTreeViewInfo;
29 import org.kuali.student.r2.core.versionmanagement.dto.VersionDisplayInfo;
30
31 import org.kuali.student.common.ui.client.application.Application;
32 import org.kuali.student.common.ui.client.application.KSAsyncCallback;
33 import org.kuali.student.common.ui.client.configurable.mvc.SectionTitle;
34 import org.kuali.student.common.ui.client.configurable.mvc.views.VerticalSectionView;
35 import org.kuali.student.common.ui.client.mvc.Callback;
36 import org.kuali.student.common.ui.client.mvc.View;
37 import org.kuali.student.common.ui.client.service.MetadataRpcService;
38 import org.kuali.student.common.ui.client.service.MetadataRpcServiceAsync;
39 import org.kuali.student.common.ui.client.widgets.KSProgressIndicator;
40 import org.kuali.student.common.ui.client.widgets.buttongroups.ButtonEnumerations;
41 import org.kuali.student.common.ui.client.widgets.field.layout.button.ActionCancelGroup;
42 import org.kuali.student.common.ui.client.widgets.progress.BlockingTask;
43 import org.kuali.student.common.ui.client.widgets.progress.KSBlockingProgressIndicator;
44 import org.kuali.student.core.statement.ui.client.widgets.rules.ReqCompEditWidget;
45 import org.kuali.student.core.statement.ui.client.widgets.rules.ReqComponentInfoUi;
46 import org.kuali.student.core.statement.ui.client.widgets.rules.RuleManageWidget;
47 import org.kuali.student.core.statement.ui.client.widgets.rules.RulesUtil;
48 import org.kuali.student.lum.common.client.widgets.*;
49 import org.kuali.student.r2.lum.clu.dto.CluInfo;
50 import org.kuali.student.lum.program.client.ProgramMsgConstants;
51 import org.kuali.student.lum.program.client.rpc.StatementRpcService;
52 import org.kuali.student.lum.program.client.rpc.StatementRpcServiceAsync;
53 import org.kuali.student.r2.lum.program.dto.ProgramRequirementInfo;
54
55
56 import com.google.gwt.core.client.GWT;
57 import com.google.gwt.user.client.Window;
58 import com.google.gwt.user.client.rpc.AsyncCallback;
59 import com.google.gwt.user.client.ui.SimplePanel;
60 import com.google.gwt.user.client.ui.VerticalPanel;
61 import com.google.gwt.user.client.ui.Widget;
62
63 public class ProgramRequirementsManageView extends VerticalSectionView {
64
65 private StatementRpcServiceAsync statementRpcServiceAsync = GWT.create(StatementRpcService.class);
66 private MetadataRpcServiceAsync metadataServiceAsync = GWT.create(MetadataRpcService.class);
67
68 protected static final String TEMLATE_LANGUAGE = "en";
69 protected static final String RULEEDIT_TEMLATE = "KUALI.RULE";
70 protected static final String RULEPREVIEW_TEMLATE = RULEEDIT_TEMLATE + ".PREVIEW";
71 protected static final String COMPOSITION_TEMLATE = "KUALI.RULE.COMPOSITION";
72 private static final String LU_NAMESPACE = "http://student.kuali.org/wsdl/lu";
73 private static final String CLU_NAMESPACE_URI = "{" + LU_NAMESPACE + "}cluInfo";
74
75 private ProgramRequirementsViewController parentController;
76
77
78 private VerticalPanel layout = new VerticalPanel();
79 private ReqCompEditWidget editReqCompWidget;
80 private RuleManageWidget ruleManageWidget;
81 private SimplePanel twiddlerPanel = new SimplePanel();
82 private ActionCancelGroup actionCancelButtons = new ActionCancelGroup(ButtonEnumerations.SaveCancelEnum.SAVE, ButtonEnumerations.SaveCancelEnum.CANCEL);
83
84
85 private StatementTreeViewInfo rule = null;
86 private boolean isInitialized = false;
87 private boolean isNewRule = false;
88 private ReqComponentInfo editedReqCompInfo = null;
89 private Integer internalProgReqID = null;
90 private String originalReqCompNL;
91 private String originalLogicExpression;
92
93
94 private BlockingTask creatingRuleTask = new BlockingTask("Creating Rule");
95
96 public ProgramRequirementsManageView(ProgramRequirementsViewController parentController, Enum<?> viewEnum, String name, String modelId) {
97 super(viewEnum, name, modelId);
98 this.parentController = parentController;
99 }
100
101 @Override
102 public void beforeShow(final Callback<Boolean> onReadyCallback) {
103
104 retrieveAndSetupReqCompTypes();
105 if (!isInitialized) {
106 setupHandlers();
107 draw();
108 isInitialized = true;
109 }
110
111 onReadyCallback.exec(true);
112 }
113
114 private void setupHandlers() {
115 editReqCompWidget.setReqCompConfirmButtonClickCallback(actionButtonClickedReqCompCallback);
116
117 editReqCompWidget.setNewReqCompSelectedCallbackCallback(newReqCompSelectedCallbackCallback);
118
119 editReqCompWidget.setRetrieveCompositionTemplateCallback(retrieveCompositionTemplateCallback);
120 editReqCompWidget.setRetrieveFieldsMetadataCallback(retrieveFieldsMetadataCallback);
121 editReqCompWidget.setRetrieveCustomWidgetCallback(retrieveCustomWidgetCallback);
122 ruleManageWidget.setReqCompEditButtonClickCallback(editReqCompCallback);
123 }
124
125 private void draw() {
126
127 remove(layout);
128 layout.clear();
129
130
131 SectionTitle title = SectionTitle.generateH3Title(getLabel(ProgramMsgConstants.PROGRAMREQUIREMENTS_MANAGEVIEWPAGESTEP1TITLE));
132 title.setStyleName("KS-Program-Requirements-Manage-Step-header1");
133 layout.add(title);
134
135 layout.add(editReqCompWidget);
136
137
138 title = SectionTitle.generateH3Title(getLabel(ProgramMsgConstants.PROGRAMREQUIREMENTS_MANAGEVIEWPAGESTEP2TITLE));
139 title.setStyleName("KS-Program-Requirements-Manage-Step-header2");
140 layout.add(title);
141 layout.add(ruleManageWidget);
142
143
144 KSProgressIndicator twiddler = new KSProgressIndicator();
145 twiddler.setVisible(false);
146 twiddlerPanel.setWidget(twiddler);
147 layout.add(twiddlerPanel);
148
149 addWidget(layout);
150
151 displaySaveButton();
152 }
153
154 private void displaySaveButton() {
155 actionCancelButtons.addStyleName("KS-Program-Requirements-Save-Button");
156 actionCancelButtons.addCallback(new Callback<ButtonEnumerations.ButtonEnum>(){
157 @Override
158 public void exec(final ButtonEnumerations.ButtonEnum result) {
159 parentController.getView(ProgramRequirementsViewController.ProgramRequirementsViews.PREVIEW, new Callback<View>(){
160 @Override
161 public void exec(View preview) {
162
163 if ((result == ButtonEnumerations.SaveCancelEnum.SAVE) && isDirty()) {
164 ProgramRequirementInfo affectedRule = ((ProgramRequirementsSummaryView) preview).getRules().updateRules(getRuleTree(), internalProgReqID, isNewRule());
165 ((ProgramRequirementsSummaryView) preview).updateRequirementWidgets(affectedRule);
166 }
167 isDirty = false;
168 parentController.showView(ProgramRequirementsViewController.ProgramRequirementsViews.PREVIEW);
169 }
170 });
171 }
172 });
173 addWidget(actionCancelButtons);
174 }
175
176
177 public void setRuleTree(StatementTreeViewInfo stmtTreeInfo, boolean newRuleFlag, Integer internalProgReqID) {
178
179 if (!isInitialized) {
180 editReqCompWidget = new ReqCompEditWidget(ProgramRequirementsSummaryView.NEW_REQ_COMP_ID);
181 ruleManageWidget = new RuleManageWidget();
182 ruleManageWidget.setReqCompEditButtonClickCallback(editReqCompCallback);
183 ruleManageWidget.setRuleChangedButtonClickCallback(ruleChangedCallback);
184 }
185
186 this.internalProgReqID = internalProgReqID;
187 editedReqCompInfo = null;
188 rule = RulesUtil.clone(stmtTreeInfo);
189 isNewRule = newRuleFlag;
190 originalReqCompNL = getAllReqCompNLs();
191
192
193 editReqCompWidget.setupNewReqComp();
194 ruleManageWidget.redraw(rule, false);
195
196 }
197
198
199 public StatementTreeViewInfo getRuleTree() {
200 rule = ruleManageWidget.getStatementTreeViewInfo();
201 return rule;
202 }
203
204 public boolean isNewRule() {
205 return isNewRule;
206 }
207
208
209 protected Callback<ReqComponentInfo> editReqCompCallback = new Callback<ReqComponentInfo>(){
210 public void exec(ReqComponentInfo reqComp) {
211 setEnabled(false);
212
213 editReqCompWidget.setupExistingReqComp(reqComp);
214 editedReqCompInfo = reqComp;
215 }
216 };
217
218 protected Callback<Boolean> ruleChangedCallback = new Callback<Boolean>(){
219 public void exec(Boolean ruleChanged) {
220 actionCancelButtons.getButton(ButtonEnumerations.SaveCancelEnum.SAVE).setEnabled(ruleChanged);
221 }
222 };
223
224 protected void setEnabled(boolean enabled) {
225 ruleManageWidget.setEnabled(enabled);
226 actionCancelButtons.getButton(ButtonEnumerations.SaveCancelEnum.SAVE).setEnabled(enabled);
227 }
228
229 @Override
230 public boolean isDirty() {
231 if (!isInitialized) {
232 return false;
233 }
234
235
236 return true;
237
238
239
240
241
242
243
244
245
246
247
248
249 }
250
251 private String getAllReqCompNLs() {
252 StringBuilder NL = new StringBuilder();
253 for (StatementTreeViewInfo tree : rule.getStatements()) {
254 for (ReqComponentInfo reqComp : tree.getReqComponents()) {
255 NL.append(reqComp.getNaturalLanguageTranslation());
256 }
257 }
258 return NL.toString();
259 }
260
261
262 protected Callback<ReqComponentInfoUi> actionButtonClickedReqCompCallback = new Callback<ReqComponentInfoUi>(){
263 public void exec(final ReqComponentInfoUi reqComp) {
264
265 editReqCompWidget.setupNewReqComp();
266 setEnabled(true);
267
268
269 if (reqComp == null) {
270 return;
271 }
272
273 KSBlockingProgressIndicator.addTask(creatingRuleTask);
274
275
276 statementRpcServiceAsync.translateReqComponentToNLs(reqComp, new String[]{RULEEDIT_TEMLATE,RULEPREVIEW_TEMLATE}, TEMLATE_LANGUAGE, new KSAsyncCallback<List<String>>() {
277 public void handleFailure(Throwable caught) {
278 KSBlockingProgressIndicator.removeTask(creatingRuleTask);
279 Window.alert(caught.getMessage());
280 GWT.log("translateReqComponentToNL failed", caught);
281 }
282
283 public void onSuccess(final List<String> reqCompNL) {
284
285 reqComp.setNaturalLanguageTranslation(reqCompNL.get(0));
286 reqComp.setPreviewNaturalLanguageTranslation(reqCompNL.get(1));
287
288
289 rule = ruleManageWidget.getStatementTreeViewInfo();
290
291 if (editedReqCompInfo == null) {
292 if (rule.getStatements() != null && !rule.getStatements().isEmpty()) {
293 StatementTreeViewInfo newStatementTreeViewInfo = new StatementTreeViewInfo();
294 newStatementTreeViewInfo.setId(ProgramRequirementsSummaryView.NEW_STMT_TREE_ID + Integer.toString(ProgramRequirementsSummaryView.tempStmtTreeID++));
295 newStatementTreeViewInfo.setOperator(rule.getStatements().get(0).getOperator());
296 newStatementTreeViewInfo.getReqComponents().add(reqComp);
297 rule.getStatements().add(newStatementTreeViewInfo);
298 } else {
299 rule.getReqComponents().add(reqComp);
300
301 if (rule.getOperator() == null) {
302 rule.setOperator(StatementOperatorTypeKey.AND);
303 }
304 }
305 } else {
306 editedReqCompInfo.setNaturalLanguageTranslation(reqComp.getNaturalLanguageTranslation());
307
308 editedReqCompInfo.setReqCompFields(reqComp.getReqCompFields());
309 editedReqCompInfo.setType(reqComp.getType());
310 editedReqCompInfo = null;
311 }
312
313 ruleManageWidget.redraw(rule, true);
314 KSBlockingProgressIndicator.removeTask(creatingRuleTask);
315 }
316 });
317 }
318 };
319
320
321 protected Callback<ReqComponentInfo> newReqCompSelectedCallbackCallback = new Callback<ReqComponentInfo>(){
322 public void exec(final ReqComponentInfo reqComp) {
323 setEnabled(false);
324 }
325 };
326
327 private void retrieveAndSetupReqCompTypes() {
328
329 statementRpcServiceAsync.getReqComponentTypesForStatementType(rule.getType(), new KSAsyncCallback<List<ReqComponentTypeInfo>>() {
330 public void handleFailure(Throwable cause) {
331 GWT.log("Failed to get req. component types for statement of type:" + rule.getType(), cause);
332 Window.alert("Failed to get req. component types for statement of type:" + rule.getType());
333 }
334
335 public void onSuccess(final List<ReqComponentTypeInfo> reqComponentTypeInfoList) {
336 if (reqComponentTypeInfoList == null || reqComponentTypeInfoList.size() == 0) {
337 GWT.log("Missing Requirement Component Types", null);
338 Window.alert("Missing Requirement Component Types");
339 return;
340 }
341 editReqCompWidget.setReqCompList(reqComponentTypeInfoList);
342 editReqCompWidget.setCustomWidgets(getCustomWidgets(reqComponentTypeInfoList));
343 }
344 });
345 }
346
347 private Map<String, Widget> getCustomWidgets(List<ReqComponentTypeInfo> reqComponentTypeInfoList) {
348 Map<String, Widget> customWidgets = new HashMap<String, Widget>();
349
350 for (ReqComponentTypeInfo reqCompTypeInfo : reqComponentTypeInfoList) {
351 for (ReqCompFieldTypeInfo fieldTypeInfo : reqCompTypeInfo.getReqCompFieldTypeInfos()) {
352 if (RulesUtil.isGradeWidget(fieldTypeInfo.getId())) {
353 customWidgets.put("kuali.reqComponent.field.type.grade.id", new GradeWidget());
354 } else if (RulesUtil.isCourseWidget(fieldTypeInfo.getId())) {
355
356 final CourseWidget courseWidget = GWT.create(CourseWidget.class);
357
358 courseWidget.addGetCluNameCallback(new Callback() {
359
360 @Override
361 public void exec(Object id) {
362
363 statementRpcServiceAsync.getCurrentVersion(CLU_NAMESPACE_URI, (String)id, new AsyncCallback<VersionDisplayInfo>() {
364 @Override
365 public void onFailure(Throwable throwable) {
366 Window.alert(throwable.getMessage());
367 GWT.log("Failed to retrieve clu for id: '" + "'", throwable);
368 }
369
370 @Override
371 public void onSuccess(final VersionDisplayInfo versionInfo) {
372 statementRpcServiceAsync.getClu(versionInfo.getId(), new AsyncCallback<CluInfo>() {
373 @Override
374 public void onFailure(Throwable throwable) {
375 Window.alert(throwable.getMessage());
376 GWT.log("Failed to retrieve clu", throwable);
377 }
378
379 @Override
380 public void onSuccess(CluInfo cluInfo) {
381 courseWidget.setLabelContent(cluInfo.getVersion().getVersionIndId(), cluInfo.getOfficialIdentifier().getCode());
382 }
383 });
384 }
385 });
386
387
388 }
389 });
390
391 customWidgets.put("kuali.reqComponent.field.type.course.clu.id", courseWidget);
392 } else if (RulesUtil.isProgramWidget(fieldTypeInfo.getId())) {
393 final ProgramWidget programWidget = new ProgramWidget();
394
395 programWidget.addGetCluNameCallback(new Callback() {
396
397 @Override
398 public void exec(Object id) {
399
400 statementRpcServiceAsync.getCurrentVersion(CLU_NAMESPACE_URI, (String)id, new AsyncCallback<VersionDisplayInfo>() {
401 @Override
402 public void onFailure(Throwable throwable) {
403 Window.alert(throwable.getMessage());
404 GWT.log("Failed to retrieve clu for id: '" + "'", throwable);
405 }
406
407 @Override
408 public void onSuccess(final VersionDisplayInfo versionInfo) {
409 statementRpcServiceAsync.getClu(versionInfo.getId(), new AsyncCallback<CluInfo>() {
410 @Override
411 public void onFailure(Throwable throwable) {
412 Window.alert(throwable.getMessage());
413 GWT.log("Failed to retrieve clu", throwable);
414 }
415
416 @Override
417 public void onSuccess(CluInfo cluInfo) {
418 programWidget.setLabelContent(cluInfo.getVersion().getVersionIndId(), cluInfo.getOfficialIdentifier().getCode());
419 }
420 });
421 }
422 });
423 }
424 });
425
426 customWidgets.put("kuali.reqComponent.field.type.program.clu.id", programWidget);
427 }
428 }
429 }
430 return customWidgets;
431 }
432
433
434 protected Callback<ReqComponentInfo> retrieveCompositionTemplateCallback = new Callback<ReqComponentInfo>(){
435 public void exec(final ReqComponentInfo reqComp) {
436
437 statementRpcServiceAsync.translateReqComponentToNL(reqComp, COMPOSITION_TEMLATE, TEMLATE_LANGUAGE, new KSAsyncCallback<String>() {
438 public void handleFailure(Throwable caught) {
439 Window.alert(caught.getMessage());
440 GWT.log("translateReqComponentToNL failed for req. comp. type: '" + reqComp.getType() + "'",caught);
441 }
442
443 public void onSuccess(final String compositionTemplate) {
444 editReqCompWidget.displayFieldsStart(compositionTemplate);
445 }
446 });
447 }
448 };
449
450 protected Callback<List<String>> retrieveFieldsMetadataCallback = new Callback<List<String>>(){
451 public void exec(final List<String> fieldTypes) {
452
453 if (fieldTypes.contains("kuali.reqComponent.field.type.grade.id")) {
454 fieldTypes.add("kuali.reqComponent.field.type.gradeType.id");
455 }
456
457 metadataServiceAsync.getMetadataList(ReqCompFieldInfo.class.getName(), fieldTypes, null, new KSAsyncCallback<List<Metadata>>() {
458 public void handleFailure(Throwable caught) {
459 Window.alert(caught.getMessage());
460 GWT.log("getMetadataList failed for req. comp. types: '" + fieldTypes.toString() + "'",caught);
461 }
462
463 public void onSuccess(final List<Metadata> metadataList) {
464 editReqCompWidget.displayFieldsEnd(metadataList);
465 }
466 });
467 }
468 };
469
470 protected Callback<String> retrieveCustomWidgetCallback = new Callback<String>(){
471 public void exec(final String fieldType) {
472 if (RulesUtil.isCluSetWidget(fieldType)) {
473 String clusetType = "kuali.cluSet.type.Course";
474 if (fieldType.toLowerCase().indexOf("program") > 0) {
475 clusetType = "kuali.cluSet.type.Program";
476 }
477 editReqCompWidget.displayCustomWidget(fieldType, new BuildCluSetWidget(new CluSetRetrieverImpl(), clusetType, false));
478 }
479 }
480 };
481
482 public Integer getInternalProgReqID() {
483 return internalProgReqID;
484 }
485
486 private String getLabel(String messageKey) {
487 return Application.getApplicationContext().getUILabel(ProgramMsgConstants.PROGRAM_MSG_GROUP, messageKey);
488 }
489 }